using Amazon.Runtime.Internal.Util; using Business.Core.Enum; using Business.Core.Utilities; using Business.Domain; using Business.Dto; using Business.EntityFrameworkCore; using Business.EntityFrameworkCore.SqlRepositories; using Business.PriorityManagement; using Business.Replenishment; using Business.ReplenishmentManagement; using Business.ResourceExamineManagement.Dto; using Business.StructuredDB.SaleFcst; using Business.StructuredDB.WMS; using EFCore.BulkExtensions; using IdentityModel.Client; using Microsoft.AspNetCore.DataProtection.Repositories; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using MongoDB.Driver; using MongoDB.Driver.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RazorEngine.Compilation.ImpromptuInterface.Optimization; using System; using System.Collections.Generic; using System.ComponentModel.Design; 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.Json.SystemTextJson; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectMapping; 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 IRepository _mes_technique; /// /// 工序 /// private readonly IRepository _mes_process; /// /// 工艺关联工序 /// private readonly IRepository _mes_tech_process; /// /// 工艺工序关联工位 /// private readonly IRepository _mes_tech_proc_workshop; /// /// 物料占用记录 /// private readonly IRepository _ic_item_stockoccupy; private IRepository _mysql_ic_item_stockoccupy; /// /// 物料详情 /// private readonly IRepository _ic_item; private IRepository _mysql_ic_item; /// /// 物料BOM /// private readonly IRepository _ic_bom; private IRepository _mysql_ic_bom; /// /// 物料BOM明细 /// private readonly IRepository _ic_bom_child; private IRepository _mysql_ic_bom_child; /// /// 物料库存表 /// private readonly IRepository _ic_item_stock; private IRepository _mysql_ic_item_stock; /// /// 物料采购报价单 /// private readonly IRepository _srm_purchase; private IRepository _mysql_srm_purchase; /// /// 采购申请单 /// private readonly IRepository _srm_pr_main; private IRepository _mysql_srm_pr_main; /// /// 采购订单表 /// private readonly IRepository _srm_po_main; private IRepository _mysql_srm_po_main; /// /// 采购订单明细表 /// private readonly IRepository _srm_po_list; private IRepository _mysql_srm_po_list; /// /// 采购订单占用详情 /// private readonly IRepository _srm_po_occupy; private IRepository _mysql_srm_po_occupy; /// /// 供应商 /// private readonly IRepository _srm_supplier; private IRepository _mysql_srm_supplier; /// /// 委外工单 /// private readonly IRepository _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 IRepository _ic_substitute; /// /// 替代方案群组 /// private readonly IRepository _ic_substitute_group; /// /// 替代明细 /// private readonly IRepository _ic_substitute_group_detail; /// /// 替代方案 /// private readonly IRepository _mysql_ic_substitute; /// /// 替代方案群组 /// private readonly IRepository _mysql_ic_substitute_group; /// /// 替代明细 /// private readonly IRepository _mysql_ic_substitute_group_detail; /// /// 生产工单主表 /// private readonly IRepository _mes_morder; /// /// 生产工单子表 /// private readonly IRepository _mes_moentry; /// /// 在制工单占用记录表 /// private readonly IRepository _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 readonly ISqlRepository _empWorkDutyMaster; /// /// 雇员信息表 /// private readonly ISqlRepository _employeeMaster; /// /// 排产结果明细 /// 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; private readonly SerialNumberAppService _serialNumberAppService; /// /// 优先级 /// private readonly ReplenishmentAppService _replenishmentAppService; /// /// 计算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( IRepository mes_technique, IRepository mes_process, IRepository mes_tech_process, IRepository mes_tech_proc_workshop, IRepository ic_item, IRepository ic_bom, IRepository ic_bom_child, IRepository ic_item_stock, IRepository mes_oorder, IRepository srm_pr_main, IRepository srm_po_main, IRepository srm_po_list, IRepository srm_po_occupy, IRepository srm_purchase, IRepository ic_substitute, IRepository ic_substitute_group, IRepository ic_substitute_group_detail, IRepository mes_morder, IRepository mes_moentry, IRepository mes_mooccupy, IRepository ic_item_stockoccupy, IRepository 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 employeeMaster, ISqlRepository empWorkDutyMaster, 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, IRepository mysql_ic_substitute, IRepository mysql_ic_substitute_group, IRepository mysql_ic_substitute_group_detail, IRepository replenishmentROP, IRepository domesticTerminalFcst, ISqlRepository ASNBOLShipperDetail, IRepository standardItemModelSet, ISqlRepository invTransHist, ISqlRepository SAPInv, ISqlRepository monthlyShipmentPlan, IRepository srmPurchase, IUnitOfWorkManager unitOfWorkManager, SerialNumberAppService serialNumberAppService, ReplenishmentAppService replenishmentAppService ) { _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; _mysql_ic_substitute = mysql_ic_substitute; _mysql_ic_substitute_group = mysql_ic_substitute_group; _mysql_ic_substitute_group_detail = mysql_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; _employeeMaster = employeeMaster; _empWorkDutyMaster = empWorkDutyMaster; _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; _serialNumberAppService = serialNumberAppService; _replenishmentAppService = replenishmentAppService; } #endregion /// /// 资源检查 -- TODO:根据客户的不同标准交货期(假如客户设定10天),如果检查交期小于标准交货期(10天),则默认把建议交期调整为10天。 /// /// /// 类型(0,销售订单 1,全域订单) /// /// public async Task ReceiveResult(string ids,int type, string companyid) { 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()); 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()); return "订单行数据不存在"; } } else { //获取订单行数据 sentrys = await _mysql_crm_seorderentry.GetListAsync(p => (p.progress == "1" || p.progress == "2") && p.company_id.ToString() == companyid && !p.IsDeleted); if (!sentrys.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单行数据不存在", _currentTenant.Id.ToString()); 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()); return "没有需要检查的订单。"; } } input.company_id = sorders[0].company_id; input.factoryId = sorders[0].factory_id.GetValueOrDefault(); //资源检查入参全局变量赋值 param.company_id = input.company_id; 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.GetListAsync(p => sentrys.Select(m => m.item_number).Contains(p.item_number) && p.factory_id == input.factoryId && p.company_id == input.company_id && !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(param.company_id.ToString(), autoCreates); pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; } //数据库快照-同步mysql库数据到mongoDB中 await DbSnapShot(input.company_id, input.factoryId, bangid, pretreatments); //记录订单行的物料齐套时间 List kittingTimes = new List(); DataInitialization(boms, bangid, icitemlist, stocklist, pretreatments, sklist); _CalcBomViewAppService.morder_type = MorderEnum.XsMorder; foreach (var sorder in sorders) { param.sorderId = sorder.Id; param.company_id = input.company_id; param.factoryId = input.factoryId; //param.checkflag = true; _morderAppService.param = param; _purchaseOrderAppService.param = param; _CalcBomViewAppService.param = param; _CalcBomViewAppService.IsInverted = true; _CalcBomViewAppService.seorder = sorder;//销售订单 var orderSentrys = sentrys.Where(s => s.seorder_id == sorder.Id).ToList(); foreach (var item in orderSentrys) { //工单资源检查信息 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; dtl.prd_code = item.item_number; //获取当前物料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, 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.InsertManyAsync(_CalcBomViewAppService.mordersInsertList); } if (prmainlist.Any()) { await _srm_pr_main.InsertManyAsync(prmainlist); } if (_CalcBomViewAppService.mooccupyAllInsertList.Any()) { _CalcBomViewAppService.mooccupyAllInsertList.ForEach(s => { s.tenant_id = param.company_id.GetValueOrDefault(); s.company_id = param.company_id; s.factory_id = param.factoryId; }); await _mes_mooccupy.InsertManyAsync(_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.company_id.GetValueOrDefault(); s.company_id = param.company_id; s.factory_id = param.factoryId; }); await _mes_moentry.InsertManyAsync(_CalcBomViewAppService.moentriesInsertList); /*var mesmoentrys = ObjectMapper.Map, List>(_CalcBomViewAppService.moentriesInsertList); _businessDbContext.BulkInsert(mesmoentrys);*/ } if (_CalcBomViewAppService.orderList.Any()) { _CalcBomViewAppService.orderList.ForEach(s => { s.tenant_id = param.company_id.GetValueOrDefault(); s.company_id = param.company_id; s.factory_id = param.factoryId; }); await _mes_oorder.InsertManyAsync(_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.GenerateNewId(help.NextId()); s.tenant_id = param.company_id.GetValueOrDefault(); s.company_id = param.company_id; s.factory_id = param.factoryId; }); await _ic_item_stockoccupy.InsertManyAsync(_CalcBomViewAppService.newStockOccList); } if (_CalcBomViewAppService.srm_Po_OccupiesInsert.Any()) { _CalcBomViewAppService.srm_Po_OccupiesInsert.ForEach(s => { s.tenant_id = param.company_id.GetValueOrDefault(); s.company_id = param.company_id; s.factory_id = param.factoryId; }); await _srm_po_occupy.InsertManyAsync(_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; //检查结果写入数据库 await ExamineResultInsertDBAsync(rtn.examines); //清空快照数据 await ClearSnapShot(bangid); return JsonConvert.SerializeObject("ok"); } public async Task ExamineResultInsertDBAsync(List examines) { //检查结果写入数据库 List examineList = new List(); List bomExamineList = new List(); List mooccupyList = new List(); List moorderList = new List(); List ooderList = new List(); List purchaseList = new List(); List purchaseoccupyList = new List(); foreach (var ex in examines) { var b_ex = ObjectMapper.Map(ex); b_ex.GenerateNewId(help.NextId());// = help.NextId(); if (_CalcBomViewAppService.mordersInsertList.Any()) { var moentry = _CalcBomViewAppService.moentriesInsertList.Where(s => s.soentry_id == b_ex.sentry_id).ToList(); if (moentry != null) { var sentryMo = _CalcBomViewAppService.mordersInsertList.Where(s => moentry.Select(x => x.moentry_moid).Contains(s.mysql_id) && s.product_code == ex.prd_code).FirstOrDefault(); if (sentryMo != null) { b_ex.morder_id = sentryMo.mysql_id; b_ex.morder_no = sentryMo.morder_no; } } } b_ex.create_time = DateTime.Now; b_ex.company_id = param.company_id; b_ex.tenant_id = param.company_id; b_ex.factory_id = param.factoryId; examineList.Add(b_ex); ex.BomChildExamineList.ForEach(s => { var bc_ex = ObjectMapper.Map(s); bc_ex.GenerateNewId(help.NextId()); bc_ex.examine_id = b_ex.Id; bc_ex.company_id = param.company_id; bc_ex.tenant_id = param.company_id; bc_ex.factory_id = param.factoryId; bc_ex.create_time = DateTime.Now; bomExamineList.Add(bc_ex); if (s.mo_occupy_list != null) { var olist = ObjectMapper.Map, List>(s.mo_occupy_list); olist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); mooccupyList.AddRange(olist); } if (s.make_list != null) { var mlist = ObjectMapper.Map, List>(s.make_list); mlist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); moorderList.AddRange(mlist); } if (s.subcontracting_list != null) { var slist = ObjectMapper.Map, List>(s.subcontracting_list); slist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); ooderList.AddRange(slist); } if (s.purchase_list != null) { var plist = ObjectMapper.Map, List>(s.purchase_list); plist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); purchaseList.AddRange(plist); } if (s.purchase_occupy_list != null) { var purlist = ObjectMapper.Map, List>(s.purchase_occupy_list); purlist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); purchaseoccupyList.AddRange(purlist); } }); } using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { if (examineList.Any()) { _businessBangDbContext.BulkInsert(examineList); } if (bomExamineList.Any()) { _businessBangDbContext.BulkInsert(bomExamineList.OrderBy(s => s.num_order).ToList()); } if (mooccupyList.Any()) { _businessBangDbContext.BulkInsert(mooccupyList); } if (moorderList.Any()) { _businessBangDbContext.BulkInsert(moorderList); } if (ooderList.Any()) { _businessBangDbContext.BulkInsert(ooderList); } if (purchaseList.Any()) { _businessBangDbContext.BulkInsert(purchaseList); } if (purchaseoccupyList.Any()) { _businessBangDbContext.BulkInsert(purchaseoccupyList); } await unitOfWork.CompleteAsync(); } catch (Exception e) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "资源检查计算结果相关数据更新失败:" + e.Message, _currentTenant.Id.ToString()); unitOfWork.Dispose(); } } } //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.Any()) { 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("所选包含已评审通过采购申请,请重新选择。"); }*/ var list = prlist.GroupBy(s => new { s.icitem_id, s.pr_purchaseid, s.IsRequireGoods, s.supplier_type }); if (list.Count() > 1) { return JsonConvert.SerializeObject("所选行的物料编码、供应商名称、采购类型、供应类别必须相同"); } } else { return JsonConvert.SerializeObject("所选采购申请单未找到,请刷新界面重新操作。"); } List occupylist = _mysql_srm_po_occupy.GetListAsync(s => idList.Contains(s.polist_id.GetValueOrDefault())).Result; 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 = prlist[0].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_aqty) * prlist[0].pr_sysprice;//订单价格(含税) /*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; }); occupylist.ForEach(s => { s.polist_id = srm_Pr.Id; }); using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _businessDbContext.BulkUpdate(prlist); _businessDbContext.BulkInsert(new List { srm_Pr }); _businessDbContext.BulkUpdate(occupylist); 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(string companyid) { //TODO:先按每周四调度任务循环,周五下单处理 //拉取所有,然后根据送货周期来合并第一次得合并数据 //List prlist = _mysql_srm_pr_main.GetListAsync(s => s.state == 1 || s.state == 2).Result; //直接按间隔多少天一次来处理数据,定时任务按周四来考虑。 DateTime toTime = DateTime.Now; //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.company_id.ToString() == companyid && s.pr_ssend_date >= starttime && s.pr_ssend_date <= endtime && s.state == 1).Result; List ic_Items = _mysql_ic_item.GetListAsync(s => s.company_id.ToString() == companyid && prlist.Select(c => c.icitem_id).Contains(s.Id)).Result; var occupylist = _mysql_srm_po_occupy.GetListAsync(s => prlist.Select(c => c.Id).Contains(s.polist_id.GetValueOrDefault()) && s.company_id.ToString() == companyid && s.IsDeleted == false).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;//区分是销售订单和非销售订单的合并。 //找到是否生成了新的PR 当前数据是否已经产生合并,则不再合并。 var newPr = insetPrList.Find(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id && s.IsRequireGoods == pr.IsRequireGoods && s.supplier_type==pr.supplier_type && (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.IsRequireGoods == pr.IsRequireGoods && s.supplier_type == pr.supplier_type && (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); var prRefoccupy = occupylist.Where(s => s.polist_id == pr.Id).ToList(); newPr = help.DeepCopy(pr); newPr.GenerateNewId(help.NextId()); prRefoccupy.ForEach(a => { a.polist_id = newPr.Id; }); 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);//建议数量 newPr.pr_ssend_date = ilist.Min(s => s.pr_ssend_date);//系统建议下单日期 newPr.pr_sarrive_date = ilist.Min(s => s.pr_sarrive_date);//系统建议到达日期(建议到货日期) /* newPr.pr_psend_date = ilist.Min(s => s.pr_psend_date);//计划下单日期 newPr.pr_parrive_date = ilist.Min(s => s.pr_parrive_date);//计划到达日期 newPr.pr_rarrive_date = ilist.Min(s => s.pr_rarrive_date);//需求到货日期*/ //newPr.pr_sysprice = newPr.pr_rqty * pr.pr_price * (1 + pr.pr_rate);//系统价格(含税) newPr.pr_orderprice = newPr.pr_aqty * pr.pr_sysprice;//订单价格(含税) 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); } if (occupylist.Any()) { _businessDbContext.BulkUpdate(occupylist); } 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(string companyid) { //直接按间隔多少天一次来处理数据,定时任务按周四来考虑。 DateTime toTime = DateTime.Now; DateTime starttime = toTime.AddDays(1); DateTime endtime = toTime.AddDays(8); List prlist = _mysql_srm_pr_main.GetListAsync(s => s.company_id.ToString() == companyid && s.IsRequireGoods == 1 && s.pr_sarrive_date >= starttime && s.pr_sarrive_date <= endtime && s.state == 1).Result; if (prlist.Any()) { List purchaselist = _mysql_srm_purchase.GetListAsync(s => s.company_id.ToString() == companyid && 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 => s.company_id.ToString() == companyid && prlist.Select(c => c.pr_purchaseid).Contains(s.Id)).Result; List ic_Items = _mysql_ic_item.GetListAsync(s => s.company_id.ToString() == companyid && prlist.Select(c => c.icitem_id).Contains(s.Id)).Result; PoActionListDto poaction = new PoActionListDto(); param.company_id = prlist[0].company_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.BulkUpdate(poaction.poOccupiesList); } if (poaction.poMasterList.Any()) { poaction.poMasterList.ForEach(s => { s.ReqBy = "DO"; }); _purOrdMaster.Insert(poaction.poMasterList); //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值 List nbrs = poaction.poMasterList.Select(a => a.PurOrd).ToList(); var nbrList = _purOrdMaster.Select(a => a.Domain == poaction.poMasterList[0].Domain && 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("PrAutoApprove", "要货令转采购订单失败:" + 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("所选包含评审未通过要货令,请重新选择。"); }*/ if (prlist.Where(s => s.IsRequireGoods == 0).Count() > 0) { return JsonConvert.SerializeObject("包含采购申请,不允许与要货令转采购订单。"); } if (prlist.Select(s => s.supplier_type).Count() > 1) { 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.company_id = prlist[0].company_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.BulkUpdate(poaction.poOccupiesList); } if (poaction.poMasterList.Any()) { poaction.poMasterList.ForEach(s => { s.ReqBy = "DO"; }); _purOrdMaster.Insert(poaction.poMasterList); //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值 List nbrs = poaction.poMasterList.Select(a => a.PurOrd).ToList(); var nbrList = _purOrdMaster.Select(a => a.Domain == poaction.poMasterList[0].Domain && 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.GetListAsync(x => seIds.Contains(x.soentry_id.Value)).Result; List mordersList = _mes_morder.GetListAsync(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.rstate = 1; se.sys_material_date = newExm.sys_material_date; se.sys_capacity_date = newExm.sys_capacity_date; //如果计算记录有工单id,则代表有生成工单,而不是占用计划工单 if (newExm.morder_id.GetValueOrDefault() != 0) { var meList = moentry.Where(s => s.soentry_id == se.Id && s.bang_id == newExm.bangid).ToList(); if (!meList.Any()) { //补救场景,假设mongdb数据丢失,从一个json格式中获取数据//此处暂不考虑 } var molist = mordersList.Where(s => meList.Select(c => c.moentry_moid).Contains(s.mysql_id) && s.bang_id == newExm.bangid).ToList(); if (!molist.Any()) { //补救场景,假设mongdb数据丢失,从一个json格式中获取数据//此处暂不考虑 } WriteMoentry.AddRange(meList); WriteMorder.AddRange(molist); } 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)); List childExamineList = _mysql_bom_child_examine.GetListAsync(c => exmResult.Select(x => x.Id).Contains(c.examine_id.GetValueOrDefault())).Result; //同步工单 CreateWorkOrdDates(moderlist, allRoutings, workOrds, workOrdRoutings, workOrdDetails, exmResult, childExamineList); } //当前订单号所关联的最新计算结果里的占用记录 List mooccupyList = await _mes_mooccupy.GetListAsync(s => seIds.Contains(s.moo_id_billid.Value) && bangidList.Contains(s.bang_id.Value)); //委外工单计算记录 List oorderList = await _mes_oorder.GetListAsync(s => seIds.Contains(s.sentry_id.Value) && bangidList.Contains(s.bang_id.Value)); //PO占用记录 List po_occupy = await _srm_po_occupy.GetListAsync(s => seIds.Contains(s.eid.Value) && bangidList.Contains(s.bang_id.Value)); List prmainlist = await _srm_pr_main.GetListAsync(s => seIds.Contains(s.sentry_id.Value) && bangidList.Contains(s.bang_id.Value)); if (prmainlist.Any()) { var nbrlistDto = _serialNumberAppService.GetBillNo(prmainlist[0].factory_id.ToString(), "PR", prmainlist.Count, "admin", 1); int index = 0; foreach (var p in prmainlist) { if (nbrlistDto[index] != null) { p.pr_billno = nbrlistDto[index].NbrResult; } index++; if (p.pr_purchaseid.GetValueOrDefault() == 0) { //数据丢失 var list = _mysql_srm_purchase.GetListAsync(s => s.icitem_id == p.icitem_id).Result; if (list.Any()) { p.pr_purchaseid = list[0].supplier_id; p.pr_purchasename = list[0].supplier_name; p.pr_purchasenumber = list[0].supplier_number; } } } } List item_stockoccupy = await _ic_item_stockoccupy.GetListAsync(s => seIds.Contains(s.orderentry_id.Value) && bangidList.Contains(s.bang_id)); 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); } var DBworkOrdList = _workOrdMaster.Select(a => a.Domain == workOrds[0].Domain && workOrds.Select(c => c.WorkOrd).Contains(a.WorkOrd)); if (workOrdRoutings.Any()) { workOrdRoutings.ForEach(c => { c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID; }); _workOrdRouting.Insert(workOrdRoutings); } if (workOrdDetails.Any()) { workOrdDetails.ForEach(c => { c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID; }); _workOrdDetail.Insert(workOrdDetails); } 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); } if (item_stockoccupy.Any()) { var sklist = ObjectMapper.Map, List>(item_stockoccupy); sklist.ForEach(s => { s.GenerateNewId(help.NextId()); s.create_time = DateTime.Now; }); _businessDbContext.BulkInsert(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.GetListAsync(p => icBoms.Select(m => m.mysql_id).Contains(p.bom_id) && p.company_id == param.company_id && !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.GetListAsync(p => childList.Select(m => m.icitem_id).ToList().Contains(p.icitem_id) && p.use_status == 1 && p.company_id == param.company_id && !p.IsDeleted).Result.ToList(); foreach (var chd in childList) { var curBoms = boms.Where(p => p.icitem_id == chd.icitem_id).ToList(); GetIcBomData(curBoms, bomlist, bomchildlist); } } /// /// 删除旧订单行数据 /// /// /// /// /// 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? companyId, 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 => p.company_id == companyId && 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); } }); var moIcitemStokc = ObjectMapper.Map, List>(icitemStokc); moIcitemStokc.ForEach(item => { item.GenerateNewId(help.NextId()); }); //插入数据 await _ic_item_stock.InsertManyAsync(moIcitemStokc); } var workordmsters = _workOrdMaster.Select(s => s.Domain == factoryId.ToString() && s.Status.ToLower() != "c"); if (workordmsters.Any()) { //根据工单表找到工单明细,然后根据DOP工单占用记录,对比工单明细发货数量,来做冲销。 var workdetails = _workOrdDetail.Select(s => workordmsters.Select(c => c.WorkOrd).Contains(s.WorkOrd)); //物料库存占用记录表 var item_occupy = _mysql_ic_item_stockoccupy.GetListAsync(p => p.company_id == companyId && itemIds.Contains(p.icitem_id)&& workordmsters.Select(c => c.WorkOrd).Contains(p.morder_mo)).Result; if (item_occupy.Any()) { item_occupy.ForEach(s => { //TODO:对发布数量和占用数量进行对冲,因为目前没有处理不同层级下使用相同物料的占用的问题。dop占用有项次号,而wms的发布数量明细没有项次号 var wdtl = workdetails.Where(x => x.WorkOrd == s.morder_mo && x.ItemNum == s.icitem_number).ToList(); if (wdtl.Any()) { foreach (var dtl in wdtl) { if (s.quantity - dtl.QtyPosted > 0) { s.quantity -= dtl.QtyPosted; dtl.QtyPosted = 0; } else { dtl.QtyPosted -= s.quantity; s.quantity = 0; } } } }); item_occupy = item_occupy.Where(s => s.quantity > 0).ToList(); if (item_occupy.Count > 0) { var mo_item_occupy = ObjectMapper.Map, List>(item_occupy); mo_item_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await _ic_item_stockoccupy.InsertManyAsync(mo_item_occupy); } } //工单主表 var mes_morder = _mysql_mes_morder.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && workordmsters.Select(c => c.WorkOrd).Contains(x.morder_no)).Result; if (mes_morder.Count > 0) { mes_morder.ForEach(item => { item.bang_id = bangid; }); var moMes_morder = ObjectMapper.Map, List>(mes_morder); moMes_morder.ForEach(item => { item.GenerateNewId(help.NextId()); }); await _mes_morder.InsertManyAsync(moMes_morder); } //工单子表 var mes_moentry = _mysql_mes_moentry.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId).Result; if (mes_moentry.Count > 0) { mes_moentry.ForEach(item => { item.bang_id = bangid; }); var moMes_moentry = ObjectMapper.Map, List>(mes_moentry); moMes_moentry.ForEach(item => { item.GenerateNewId(help.NextId()); }); await _mes_moentry.InsertManyAsync(moMes_moentry); } //在制工单占用记录表 var mes_mooccupy = _mysql_mes_mooccupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && mes_morder.Select(c => c.morder_no).Contains(x.moo_mo)).Result; if (mes_mooccupy.Count > 0) { var moMes_mooccupy = ObjectMapper.Map, List>(mes_mooccupy); moMes_mooccupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await _mes_mooccupy.InsertManyAsync(moMes_mooccupy); } } //根据物料信息,只同步在途未关闭的采购订单和采购申请 //采购订单明细 var srm_po_list = _mysql_srm_po_list.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result; if (srm_po_list.Count > 0) { //采购订单--取出状态为在途的PO var srm_po_main = _mysql_srm_po_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_po_list.Select(c => c.po_id).Contains(x.Id) && x.state != 3).Result; if (srm_po_main.Count > 0) { var moSrm_po_main = ObjectMapper.Map, List>(srm_po_main); moSrm_po_main.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await _srm_po_main.InsertManyAsync(moSrm_po_main); //订单明细--根据在途PO过滤出有效的Po_list srm_po_list = srm_po_list.Where(s => srm_po_main.Select(x => x.Id).Contains(s.po_id.GetValueOrDefault())).ToList(); var moSrm_po_list = ObjectMapper.Map, List>(srm_po_list); moSrm_po_list.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await _srm_po_list.InsertManyAsync(moSrm_po_list); } //采购订单明细占用详情 var srm_po_occupy = _mysql_srm_po_occupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_po_list.Select(c => c.Id).Contains(x.polist_id.GetValueOrDefault())).Result; if (srm_po_occupy.Count > 0) { var moSrm_po_occupy = ObjectMapper.Map, List>(srm_po_occupy); moSrm_po_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await _srm_po_occupy.InsertManyAsync(moSrm_po_occupy); } } //pr var srm_pr_main = _mysql_srm_pr_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result; if(srm_pr_main.Count>0) { var moSrm_pr_main = ObjectMapper.Map, List>(srm_pr_main); moSrm_pr_main.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await _srm_pr_main.InsertManyAsync(moSrm_pr_main); //采购申请占用详情 var srm_pr_occupy = _mysql_srm_po_occupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_pr_main.Select(c => c.Id).Contains(x.polist_id.GetValueOrDefault())).Result; if (srm_pr_occupy.Count > 0) { var moSrm_pr_occupy = ObjectMapper.Map, List>(srm_pr_occupy); moSrm_pr_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await _srm_po_occupy.InsertManyAsync(moSrm_pr_occupy); } } } /// /// 清处数据库快照 /// /// public async Task ClearSnapShot(long bangid) { //清除物料库存数据 await _ic_item_stock.DeleteAsync(p => p.bang_id == bangid); //清除工单占用记录表 //await _mes_mooccupy.DeleteAsync(p => p.bang_id == bangid); //清除工单主表 //await _mes_morder.Delete(p => p.bang_id == bangid); //清除工单子表 //await _mes_moentry.Delete(p => p.bang_id == bangid); //清除采购订单 await _srm_po_main.DeleteAsync(p => p.bang_id == bangid); //清除采购订单明细 await _srm_po_list.DeleteAsync(p => p.bang_id == bangid); //清除采购订单占用详情 //await _srm_po_occupy.DeleteAsync(p => p.bang_id == bangid); //清除PR //await _srm_pr_main.DeleteAsync(p => p.bang_id == bangid); } /// /// 根据物料id获取物料4个提前期 /// /// 物料id /// 企业id /// 工厂id /// private List GetLeadTime(List icItemIds, long? companyId, long factoryid) { return icItemIds.Where(p => p.factory_id == factoryid && p.company_id == companyId && !p.IsDeleted). Select(x => new ICItemLeadTimeDto { item_id = x.mysql_id, transportation_leadtime = x.transportation_leadtime, stock_leadtime = x.stock_leadtime, production_leadtime = x.production_leadtime, order_leadtime = x.order_leadtime, minorderqty = x.minorderqty, put_integer = x.put_integer, minpackqty = x.minpackqty, ordissu_days = x.ordissu_days }).AsQueryable().ToList(); } //根据物料id获取物料供应商 private List GetSupplier(List icItemIds, long? companyId, long factoryid) { return _srm_purchase.GetListAsync(p => icItemIds.Contains(p.icitem_id) && p.company_id == companyId && p.factory_id == factoryid && !p.IsDeleted).Result; } /// /// 同一周以周五为合并采购申请单截点判断是否为同一周 /// /// 基准订单时间 /// 目标订单时间 /// 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 pooccupylist = new List(); List pOGroupDtos = new List(); var occupyList = _mysql_srm_po_occupy.GetListAsync(s => list.Select(c => c.Id).Contains(s.polist_id.GetValueOrDefault()) && s.company_id == list[0].company_id && s.factory_id == list[0].factory_id && s.IsDeleted == false).Result; string domain = list[0].factory_id.ToString(); //合并条件:目前传入的数据是一周的数据,暂时不考虑多周数据合并。 //标准类 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; var icitem = itemList.First(a => a.Id == item.icitem_id); if (icitem == null) { continue; } podetail.icitem_id = item.icitem_id; podetail.model = icitem.model; podetail.ItemNum = icitem.number; podetail.icitem_name = icitem.name; podetail.qty = item.pr_aqty; podetail.netprice = item.pr_price; podetail.netmoney = item.pr_aqty.GetValueOrDefault() * item.pr_price.GetValueOrDefault(); podetail.rate = item.pr_rate; podetail.price = item.pr_sysprice; podetail.total_price = item.pr_orderprice; podetail.taxamount = item.pr_orderprice.GetValueOrDefault() - podetail.netmoney; podetail.plan_qty = item.pr_aqty; podetail.unit = item.pr_unit; podetail.state = 1; podetail.rarrdate = item.pr_sarrive_date; podetail.rnumber = 0; podetail.currencytype = item.currencytype; podetail.create_time = DateTime.Now; podetail.factory_id = param.factoryId; podetail.company_id = param.company_id; podetail.stock_id = 1; var refProccupy = occupyList.Where(s => s.polist_id == item.Id).ToList(); refProccupy.ForEach(f => { f.polist_id = podetail.Id; }); poaction.poOccupiesList.AddRange(refProccupy); 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 = help.NextId().ToString(); 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.supplier_type = dto.supplier_type; 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.company_id = param.company_id; 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_rqty; 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.company_id = param.company_id;//取销售子表企业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); var nbrlistDto = _serialNumberAppService.GetBillNo(domain, "DO", polist.Count, "admin", 1); int index = 0; foreach (var p in polist) { if (nbrlistDto[index] != null) { var podtls = podetaillist.Where(s => s.po_billno == p.po_billno).ToList(); p.po_billno = nbrlistDto[index].NbrResult; podtls.ForEach(s => { s.po_billno = p.po_billno; }); } index++; } List purOrdMasters = new List(); polist.ForEach(a => { purOrdMasters.Add(new PurOrdMaster { Domain = domain, Potype = poType == 1 ? "po" : "pw", PurOrd = a.po_billno, Buyer = a.po_purchaser_no, OrdDate = a.po_ssend_date, Curr = "CNY", Supp = a.supplier_no, Tax1 = a.po_tax_rate.GetValueOrDefault(), Department = a.purchasing_orgname, CustPhone = a.suppliertelephone, CustAddress = a.supplierdddress, USAGE = a.supplier_type, 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 = domain, 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.GetValueOrDefault(), StdCost = a.price.GetValueOrDefault() / (1 + a.rate.GetValueOrDefault()), TaxRate = a.rate.GetValueOrDefault(), 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(string domain) { if (string.IsNullOrEmpty(domain)) { return "当前任务工厂编号为空,请检查。"; } List Mes_Morders = _mysql_mes_morder.GetListAsync(x => x.morder_state == "初始" && x.factory_id.ToString() == domain).Result; /*//先排除锁定期内的工单 //优先级排序 var sysSet = _generalizedCodeMaster.Select(s => s.FldName == "SystemConfig" && s.Val == "WorkOrderLockPeriod" && s.Domain == domain).ToList(); decimal lookDay = 0; if (sysSet.Any()) { //锁定期 lookDay = sysSet[0].UDeci1; } lookDay = lookDay == 0 ? 7 : lookDay; DateTime lookTime = DateTime.Now.Date.AddDays((double)lookDay); Mes_Morders = Mes_Morders.Where(s => s.moentry_sys_stime > lookTime || s.moentry_sys_stime == null).OrderBy(s => s.moentry_sys_stime).ToList();*/ if (Mes_Morders.Any()) { List monolist = Mes_Morders.Select(c => c.morder_no).ToList(); #region PR的清除目前不处理,待后续二期方案解决。 /*Mes_Morders.ForEach(s => { s.moentry_sys_stime = DateTime.Now.Date.AddDays((double)lookDay + 1); }); //清理PR的占用。 //如果PR没有转PO,则PR没有合并,就删除,有合并,就减少合并后的PR的数量。 var prlist = _mysql_srm_pr_main.GetListAsync(s => monolist.Contains(s.pr_mono)).Result; List alllist = new List(); List updatelist = new List(); List dellist = new List(); RecursionGetDbPr2(prlist, alllist); foreach (var pr in prlist) { //找到没有关闭的PR,如果关联上的PR都是已关闭,则说明已经转了PO。 //TODO:解决Database operation expected to affect 1 row(s) but actually affected 0 row(s). 如果业务逻辑有问题自行修改 var getPr = RerunPr(pr, alllist); if (getPr != null) { if (getPr.pr_aqty - pr.pr_aqty <= 0) { //删除这个pr,没有小于0则是更新 dellist.Add(getPr); } else { getPr.pr_aqty = getPr.pr_aqty - pr.pr_aqty; updatelist.Add(getPr); } } }*/ #endregion List occupy = await _mysql_srm_po_occupy.GetListAsync(s => monolist.Contains(s.morder_mo)); _businessDbContext.BulkDelete(occupy); /*if (updatelist.Any()) { _businessDbContext.BulkUpdate(updatelist); } if (dellist.Any()) { _businessDbContext.BulkDelete(dellist); }*/ //清理工单占用 List mooccupy = await _mysql_mes_mooccupy.GetListAsync(s => Mes_Morders.Select(c => c.Id).Contains(s.moo_id.GetValueOrDefault())); if (mooccupy.Any()) { _businessDbContext.BulkDelete(mooccupy); } //清理掉库存占用 var itemstockoccupy = _mysql_ic_item_stockoccupy.GetListAsync(s => monolist.Contains(s.morder_mo)).Result; if (itemstockoccupy.Any()) { _businessDbContext.BulkDelete(itemstockoccupy); } //清理锁定期外的排程数据.工单排产会清理重排 /*var periodList = _periodSequenceDet.Select(s => monolist.Contains(s.WorkOrds)); if (periodList.Any()) { _periodSequenceDet.Delete(s => monolist.Contains(s.WorkOrds)); } var schedulList = _scheduleResultOpMaster.Select(s => monolist.Contains(s.WorkOrd)); if (schedulList.Any()) { _scheduleResultOpMaster.Delete(s => monolist.Contains(s.WorkOrd)); }*/ //只走计划工单 var rtn = await OrderKittingCheck(Mes_Morders, true); } else { return "未查找到对应的计划工单,请联系管理员。"; } return "ok"; } /// /// 递归寻找PR,找到合并后的PR /// public void RecursionGetDbPr2(List list, List referlist) { List prlist = _mysql_srm_pr_main.GetListAsync(s => list.Select(c => c.refer_pr_billno).Contains(s.pr_billno)).Result; if (prlist.Any()) { referlist.AddRange(prlist); RecursionGetDbPr2(prlist, referlist); } } //找到没有关闭的PR,做数量的减少 public srm_pr_main RerunPr(srm_pr_main pr, List referlist) { //如果当前PR已经关闭,则检查合并数据 if (pr.state == 0) { //已关闭,并且没有关联数据,则代表转PO了。 var refPr = referlist.Find(s => s.pr_billno == pr.refer_pr_billno); //如果有关联,继续往下查 if (refPr != null) { return RerunPr(refPr, referlist); } else { return null; } } else { return pr; } } /// /// 范围内工单齐套检查 /// /// /// /// public async Task OrderCompleteInspection(string domain, string userAccount) { var workords = _workOrdMaster.Select(s => s.Domain == domain && (s.Status == "r" || string.IsNullOrEmpty(s.Status) == true)).ToList(); List morders = _mysql_mes_morder.GetListAsync(x => x.factory_id.ToString() == domain && workords.Select(s => s.WorkOrd).Contains(x.morder_no) && (x.morder_state == MorderEnum.Initial_state || x.morder_state == MorderEnum.Xd_state) && !x.IsDeleted).Result; if (morders.Any()) { var rst = await OrderResourceCheck(morders, domain, userAccount); if (rst == "ok") { try { await _mysql_mes_morder.UpdateManyAsync(morders); } catch (Exception e) { new NLogHelper("ResourceExamineAppService").WriteLog("OrderCompleteInspection", "工单齐套检查失败:" + e.Message, _currentTenant.Id.ToString()); } } else { return rst; } } return "ok"; } /// /// 原材料在库检查 /// /// /// public async Task OrderResourceCheck(List mo_Mes_Morders,string domain, string userAccount) { List checkMo = new List(); //只做库存是否齐套检查 if (mo_Mes_Morders.Any()) { //检查工单是否已经下了领料单 var nbrList = _nbrMaster.Select(a => a.Domain == domain && a.Type == "SM" && mo_Mes_Morders.Select(c => c.morder_no).Contains(a.WorkOrd)); foreach (var mo in mo_Mes_Morders) { //查出已产生领料单、过滤掉,取出未领料的工单 var nbr = nbrList.Find(s => s.WorkOrd == mo.morder_no); if (nbr != null) { //完成时间到了 if (nbr.EffDate.GetValueOrDefault().Date == DateTime.Now.Date) { //如果应完成日期,没有完成,则更新工单状态 if (nbr.Ufld1 == "completed") { //工单状态为 “生产齐套” mo.MaterialSituation = MorderEnum.ProduceComplete; } else { //工单状态为 “备料滞后” mo.MaterialSituation = MorderEnum.Lag; } } //完成时间未到 else if (nbr.EffDate.GetValueOrDefault().Date > DateTime.Now.Date) { //工单状态为 “备料中” mo.MaterialSituation = MorderEnum.Preparation; } //完成时间已经过去,则不做处理 } else { checkMo.Add(mo); } } if (checkMo.Any()) { var rtn = await OrderKittingCheck(checkMo); if (rtn != null && rtn.examines != null) { //循环处理工单 foreach (var cmo in checkMo) { bool flag = true; var exm = rtn.examines.Find(s => s.morder_no == cmo.morder_no); if (exm != null && exm.BomChildExamineList != null && exm.BomChildExamineList.Any()) { foreach (var bce in exm.BomChildExamineList) { //如果有缺料 if (bce.is_use && bce.stock_state == 0) { //如果当前数据没有子级,则代表原材料齐套 if (exm.BomChildExamineList.Where(s => s.parent_id == bce.fid).Count() == 0) { flag = false; break; } } } } else { flag = false; } if (flag) { //锁定期内生产备料单,并且更新为备料中,锁定期外的则更新成仓库齐套。 cmo.MaterialSituation = MorderEnum.CarehouseComplete; } else { //工单状态为 “仓库不齐套” cmo.MaterialSituation = MorderEnum.NoCarehouseComplete; } } } } return "ok"; } else { return "没有需要下达的工单"; } } //寻找子工序生成排产计划 public List GetCopyOP(string workords,string domain) { List returnList = new List(); if (string.IsNullOrEmpty(workords)) { return returnList; } List workOrd = workords.Split(",").ToList(); //工单信息 var workOrdMasters = _workOrdMaster.Select(p => p.Domain == domain && workOrd.Contains(p.WorkOrd)); //当前工单所有工序 var workordRList = _workOrdRouting.Select(s => s.Domain == domain && workOrd.Contains(s.WorkOrd)).ToList(); //产线 List prodLines = _prodLineDetail.Select(p => workOrdMasters.Select(m => m.ItemNum).Contains(p.Part) && p.Domain == domain && p.IsActive); //获取已排产的工单 List dbPeriodSequences = _periodSequenceDet.Select(p => workOrd.Contains(p.WorkOrds) && p.Domain == domain && p.IsActive); List copyList = new List(); foreach (var work in workOrd) { List alllist = workordRList.Where(s => s.WorkOrd == work).ToList(); List parentlist = alllist.Where(s => s.WorkOrd == work && s.ParentOp == 0).ToList(); //非关键工序也要添加 copyList.AddRange(parentlist.Where(s => s.MilestoneOp == false).ToList()); GetChildOP(parentlist, alllist, copyList); } foreach (var wor in copyList) { var workPsd = dbPeriodSequences.Where(s => s.ItemNum == wor.ItemNum && s.WorkOrds == wor.WorkOrd).ToList(); var line = prodLines.Where(p => p.Part == wor.ItemNum && p.Op == wor.OP).FirstOrDefault(); foreach (var psd in workPsd) { var newPsd = new PeriodSequenceDet { Domain = domain, //Line = item.Line, ItemNum = wor.ItemNum, PlanDate = psd.PlanDate, Period = 1,//目前只考虑一班制 OrdQty = psd.OrdQty, WorkOrds = wor.WorkOrd, Op = wor.OP, IsActive = true, Status = "", CreateTime = DateTime.Now }; if (line != null) { newPsd.Line = line.Line; } else { newPsd.Line = psd.Line; } returnList.Add(newPsd); } } return returnList; } //递归寻找到子级工序里工序编码最大的一条记录。 public void GetChildOP(List parentlist, List alllist, List copyList) { foreach (var parent in parentlist) { var list = alllist.Where(s => s.ParentOp == parent.OP).ToList(); if (list.Any()) { var maxOp = list.OrderByDescending(s => s.OP).FirstOrDefault(); if (maxOp != null) { copyList.Add(maxOp); } GetChildOP(list, alllist, copyList); } } } /// /// 自动下达 /// /// /// /// /// public async Task ProduceDayPlanKittingCheck(string startime,string endtime,string domain, string userAccount) { DateTime stime = DateTime.Now.Date.AddDays(-100); if (!string.IsNullOrEmpty(startime)) { DateTime.TryParse(startime, out stime); } DateTime etime = DateTime.Now.Date.AddYears(2); if (!string.IsNullOrEmpty(endtime)) { DateTime.TryParse(endtime, out etime); } //根据排产日计划来获取 var periodSd = _periodSequenceDet.Select(s => s.Domain == domain && string.IsNullOrEmpty(s.Status) == true && stime <= s.PlanDate && s.PlanDate <= etime).ToList(); if (periodSd.Any()) { List morders = _mysql_mes_morder.GetListAsync(x => domain == x.factory_id.ToString() && periodSd.Select(s => s.WorkOrds).Contains(x.morder_no) && (x.morder_state == MorderEnum.Initial_state || x.morder_state == MorderEnum.Xd_state) && !x.IsDeleted).Result; if (!morders.Any()) { return "没有需要下达的工单"; } var rst = await OrderResourceCheck(morders, domain, userAccount); if (rst == "ok") { var sysSet = _generalizedCodeMaster.Select(s => s.FldName == "SystemConfig" && s.Val == "WorkOrderLockPeriod" && s.Domain == domain).ToList(); decimal lookDay = 0; if (sysSet.Any()) { //锁定期 lookDay = sysSet[0].UDeci1; } lookDay = lookDay == 0 ? 7 : lookDay; DateTime lookTime = DateTime.Now.Date.AddDays((double)lookDay); string workords = ""; foreach (var mo in morders) { if (mo.MaterialSituation == MorderEnum.CarehouseComplete && mo.morder_state == MorderEnum.Initial_state && mo.moentry_sys_stime.GetValueOrDefault().Date <= lookTime) { workords += "," + mo.morder_no; mo.morder_state = MorderEnum.Xd_state; } } await _mysql_mes_morder.UpdateManyAsync(morders); if (workords.Length > 0) { workords = workords.Substring(1, workords.Length - 1); //如果生成领料单,需清理掉当前工单的占用,然后根据领料单的数据,来生成工单的占用 var pickRst = await CreatePickBill(workords, domain, userAccount); if (pickRst != "ok") { return pickRst; } var insertList = GetCopyOP(workords, domain); if (insertList.Any()) { _periodSequenceDet.Insert(insertList); } } return "ok"; } else { return rst; } } else { return "没有需要下达的工单"; } } /// /// 手动按工单下达 /// /// /// /// /// public async Task ProduceWorkOrdKittingCheck(string workord, string domain,string userAccount) { if (!string.IsNullOrEmpty(workord)) { List morders = _mysql_mes_morder.GetListAsync(x => domain == x.factory_id.ToString() && x.morder_no == workord && !x.IsDeleted).Result; if (morders.Any()) { if (!string.IsNullOrEmpty(morders[0].morder_state) && morders[0].morder_state != MorderEnum.Initial_state) { return "工单信息为"+ morders[0].morder_state + ",不允许下达。"; } var rst = await OrderResourceCheck(morders, domain, userAccount); if (rst == "ok") { try { morders[0].morder_state = MorderEnum.Xd_state; morders[0].MaterialSituation = morders[0].MaterialSituation == MorderEnum.NoCarehouseComplete ? MorderEnum.Part : morders[0].MaterialSituation; //如果生成领料单,需清理掉当前工单的占用,然后根据领料单的数据,来生成工单的占用 var pickRst = await CreatePickBill(morders[0].morder_no, domain, userAccount); if (pickRst != "ok") { return pickRst; } await _mysql_mes_morder.UpdateManyAsync(morders); //复制子工序 var insertList = GetCopyOP(morders[0].morder_no, domain); if (insertList.Any()) { _periodSequenceDet.Insert(insertList); } return "ok"; } catch (Exception e) { return "下达失败,请联系管理员。"; } } else { return rst; } } else { return "工单信息不存在,请重新检查。"; } } else { return "没有需要下达的工单"; } } /// /// 工单齐套检查/替代料齐套检查结果保存 /// /// /// 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.company_id = param.company_id; 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.company_id = param.company_id; 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.company_id = param.company_id; 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("没有需要检查的工单"); }*/ return "ok"; } /// /// 检查结果组装 /// /// /// /// 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()) { return rtn; } //资源检查入参全局变量赋值 param.company_id = mo_Mes_Morders[0].company_id; param.factoryId = mo_Mes_Morders[0].factory_id.GetValueOrDefault(); 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;*/ var morderIdList = mo_Mes_Morders.Select(s => s.Id).ToList(); List mo_Mes_Moentries = _mysql_mes_moentry.GetListAsync(x => morderIdList.Contains(x.moentry_moid.Value)).Result; //获取订单行数据 List sentrys = _mysql_crm_seorderentry.GetListAsync(p => p.company_id == param.company_id && p.factory_id == param.factoryId && !p.IsDeleted && mo_Mes_Moentries.Select(x => x.soentry_id).Contains(p.Id)).Result; //删除同步Mysql后旧数据 await DeleteMySqlOldData(sentrys); List boms = _ic_bom.GetListAsync(p => mo_Mes_Morders.Select(m => m.bom_number).Contains(p.bom_number) && p.factory_id == param.factoryId && p.company_id == param.company_id && !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(param.company_id.ToString(), autoCreates); pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; } //数据库快照-同步mysql库数据到mongoDB中 await DbSnapShot(param.company_id, param.factoryId, bangid, pretreatments); DataInitialization(boms, bangid, icitemlist, stocklist, pretreatments, sklist); //调用优先级计算算法 var workOrds = _replenishmentAppService.CalcPriority(mo_Mes_Morders.Select(p => p.morder_no).ToList(), param.factoryId.ToString()); List priorityMorderList = new List(); foreach (var work in workOrds) { var mo = mo_Mes_Morders.Find(s => s.morder_no == work.WorkOrd); if (mo != null) { priorityMorderList.Add(mo); } } if (!planCheck) { //如果是齐套检查,则不考虑其他数据的占用,只看原材料库存 sklist = new List(); } _morderAppService.param = param; _purchaseOrderAppService.param = param; _CalcBomViewAppService.param = param; _CalcBomViewAppService.IsInverted = true; foreach (var item in priorityMorderList) { var moentry = mo_Mes_Moentries.Find(s => s.moentry_moid == item.Id); if (moentry == null) { continue; } var sentry = sentrys.Find(s => s.Id == moentry.soentry_id); //工单资源检查信息 ExamineResult dtl = new ExamineResult(); dtl.morder_id = item.Id; dtl.morder_no = item.morder_no; dtl.bangid = bangid; dtl.order_statr_time = item.start_time; dtl.bom_number = item.bom_number; dtl.need_qty = item.need_number.GetValueOrDefault(); dtl.prd_code = item.product_code; //获取当前物料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.morder_type = item.morder_type; _CalcBomViewAppService.mes_morder = item; //库存初始化 _CalcBomViewAppService.BomStock(getBomList, stocklist, bangid); //计算 _CalcBomViewAppService.CalcView(getBomList, bangid, item.need_number.GetValueOrDefault(), item.moentry_sys_stime, sklist, sentry, icitemlist); //TODO:最晚开始时间 var curFacDtl = leadTimeList.FirstOrDefault(p => p.item_id == childBom.icitem_id); //物料齐套时间 dtl.kitting_times = getBomList.Where(p => p.is_use && p.kitting_time != null).OrderByDescending(m => m.kitting_time).First().kitting_time.GetValueOrDefault(); //替代关系展开list dtl.BomChildExamineList = getBomList; //添加订单行开工信息 examines.Add(dtl); } rtn.examines = examines; if (planCheck) { //如果有计划工单,则需要生成pr po oo List prmainlist = new List(); 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) && p.Domain == param.factoryId.ToString()); workOrdMasters.ForEach(s => { var mo = mo_Mes_Morders.Find(m => m.morder_no == s.WorkOrd); if (mo != null) { s.OrdDate = mo.moentry_sys_stime; s.DueDate = mo.moentry_sys_stime; } }); using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _businessDbContext.BulkUpdate(mo_Mes_Morders); if (workOrdMasters.Any()) { _workOrdMaster.Update(workOrdMasters); } if (prmainlist.Any()) { var pr_mainlist = ObjectMapper.Map, List>(prmainlist); _businessDbContext.BulkInsert(pr_mainlist); } if (_CalcBomViewAppService.newStockOccList.Any()) { var stockoccupylist = ObjectMapper.Map, List>(_CalcBomViewAppService.newStockOccList); stockoccupylist.ForEach(s => { s.create_time = DateTime.Now; s.tenant_id = param.company_id.GetValueOrDefault(); s.company_id = param.company_id; s.factory_id = param.factoryId; }); _businessDbContext.BulkInsert(stockoccupylist); } if (_CalcBomViewAppService.srm_Po_OccupiesInsert.Any()) { _CalcBomViewAppService.srm_Po_OccupiesInsert.ForEach(s => { s.company_id = param.company_id; s.factory_id = param.factoryId; }); await _srm_po_occupy.InsertManyAsync(_CalcBomViewAppService.srm_Po_OccupiesInsert); } await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("OrderKittingCheck", "工单检查数据更新失败:" + e.Message, _currentTenant.Id.ToString()); } } } //检查结果写入数据库 await ExamineResultInsertDBAsync(examines); //清空快照数据 await ClearSnapShot(bangid); return rtn; } /// /// 物料数据计算前准备 /// /// /// /// /// /// /// /// /// /// /// /// /// public void DataInitialization(List boms, long bangid, List icitemlist, List stocklist, List pretreatments, List sklist) { List itemIds = pretreatments.Select(p => p.item_id.GetValueOrDefault()).ToList(); icitemlist.AddRange(_ic_item.GetListAsync(p => itemIds.Contains(p.mysql_id) && !p.IsDeleted).Result); #region 1、数据准备 //1.1、获取产能检查相关数据 //产品物料编码 List itemnums = pretreatments.Where(p => p.level == 1).Select(p => p.item_number).Distinct().ToList(); //产线明细 prodLines = _prodLineDetail.Select(p => itemnums.Contains(p.Part)).ToList(); //标准工序 routingOps = _routingOpDetail.Select(p => 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.GetListAsync(x => boms.Select(p => p.item_number).Contains(x.product_code) && (x.morder_state != MorderEnum.Accomplish_state || x.morder_state != MorderEnum.Close_state && x.morder_icitem_type != MorderEnum.XgwyMorder) && x.company_id == param.company_id && x.factory_id == param.factoryId && x.bang_id == bangid).Result; List moids = mo_Mes_Morders.Select(p => p.mysql_id).ToList(); List mo_Mes_Moentry = _mes_moentry.GetListAsync(x => moids.Contains(x.moentry_moid)).Result; //工单占用表 List mes_mooccupyList = _mes_mooccupy.GetListAsync(x => x.moo_state == 1 && !x.IsDeleted && x.company_id == param.company_id && boms.Select(p => p.item_number).Contains(x.fitem_number) && x.bang_id == bangid).Result; List occoupyRefId = new List(); //物料采购订单明细 var poDetailList = _srm_po_list.GetListAsync(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state == 1 && x.rstate == 1 && !x.IsDeleted).Result; occoupyRefId.AddRange(poDetailList.Select(p => p.Id).ToList()); var srm_pr_mains = _srm_pr_main.GetListAsync(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state != 0 && !x.IsDeleted).Result; occoupyRefId.AddRange(srm_pr_mains.Select(p => p.Id).ToList()); //采购订单或采购申请占用数据 var poOccupys = _srm_po_occupy.GetListAsync(x => occoupyRefId.Contains(x.polist_id) && x.bang_id == bangid && !x.IsDeleted).Result; #endregion //处理一下已经插入得占用记录 //物料库存 stocklist.AddRange(_ic_item_stock.GetListAsync(p => p.factory_id == param.factoryId && p.bang_id == bangid && itemIds.Contains(p.icitem_id)).Result); //物料库存占用表 sklist.AddRange(_ic_item_stockoccupy.GetListAsync(x => x.bang_id == bangid && !x.IsDeleted && itemIds.Contains(x.icitem_id)).Result); //物料提前期 leadTimeList = GetLeadTime(icitemlist, param.company_id, param.factoryId);//提前期列表 supplierList = GetSupplier(itemIds, param.company_id, param.factoryId);//供应商列表 _CalcBomViewAppService.leadTimeList = leadTimeList; _CalcBomViewAppService.supplierList = supplierList; //资源检查添加产线工序等数据 _CalcBomViewAppService.prodLines = prodLines; _CalcBomViewAppService.routingOps = routingOps; _CalcBomViewAppService.calendarWorks = calendarWorks; _CalcBomViewAppService.qualityLineWorks = qualityLineWorks; _CalcBomViewAppService.holidays = holidays; _CalcBomViewAppService.mordersList = mo_Mes_Morders;//工单 _CalcBomViewAppService.moentriesList = mo_Mes_Moentry;//工单子表 _CalcBomViewAppService.mooccupyAllList = mes_mooccupyList;//工单占用表 _CalcBomViewAppService.srm_Po_Lists = poDetailList; //采购明细 _CalcBomViewAppService.srm_Po_Occupies = poOccupys; //采购占用表 _CalcBomViewAppService.ic_item_List = icitemlist; //物料表 _CalcBomViewAppService.srm_Pr_Mains = srm_pr_mains.Where(s=>s.state != 4).ToList();//PR DateTime dt = DateTime.Now; _CalcBomViewAppService.quarter_starttime = dt.AddMonths(0 - (dt.Month - 1) % 3).AddDays(1 - dt.Day).Date; _CalcBomViewAppService.quarter_endtime = _CalcBomViewAppService.quarter_starttime.AddMonths(3); _CalcBomViewAppService.quarter_srm_pr_mains = srm_pr_mains.Where(s => s.pr_psend_date >= _CalcBomViewAppService.quarter_starttime && s.pr_psend_date < _CalcBomViewAppService.quarter_endtime).ToList();//本季度PR } public void GenerateSort(List returnlist) { int level = returnlist.Max(s => s.level); returnlist.ForEach(s => { int num = level - s.level; if (num > 0) { s.num_order = long.Parse((s.num_order * Math.Pow(1000, num)).ToString()); } }); } /// /// 物料和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).Distinct().ToList(); sublist.AddRange(_ic_substitute.GetListAsync(p => codeList.Contains(p.substitute_code) && !p.IsDeleted).Result); List subidlist = sublist.Select(c => c.mysql_id).Distinct().ToList(); suballlist.AddRange(_ic_substitute_group.GetListAsync(p => subidlist.Contains(p.substitute_group_id) && !p.IsDeleted).Result); List suballidlist = suballlist.Select(c => c.mysql_id).Distinct().ToList(); subdtllist.AddRange(_ic_substitute_group_detail.GetListAsync(p => suballidlist.Contains(p.substitute_group_id) && !p.IsDeleted).Result); //获取物料数据 List itemIds = bomlist.Select(p => p.icitem_id).ToList(); itemIds.AddRange(bomchildlist.Select(p => p.icitem_id).ToList()); itemIds.AddRange(subdtllist.Select(p => p.icitem_id).ToList()); icitemlist.AddRange(_ic_item.GetListAsync(p => itemIds.Contains(p.mysql_id) && !p.IsDeleted).Result); } /// /// 自动生成BOM预处理清单 /// public void AutoCreateBomBill(string companyid,List ic_Boms = null) { ic_Boms ??= _ic_bom.GetListAsync(p => p.company_id.ToString() == companyid && !p.IsDeleted).Result.ToList(); var pretreatment = _mysql_b_bom_pretreatment.GetListAsync(s => ic_Boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; param.company_id = long.Parse(companyid); //物料bom List bomlist = new List(); List bomchildlist = new List(); //物料信息 List icitemlist = new List(); //替代关系 List sublist = new List(); List suballlist = new List(); List subdtllist = new List(); IcItemPretreatment(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; s.company_id = bom.company_id; s.tenant_id = bom.tenant_id; s.factory_id = bom.factory_id; }); addList.AddRange(list); } if (deleteList.Any()) { _businessDbContext.BulkDelete(deleteList); } if (addList.Any()) { _businessDbContext.BulkInsert(addList); //await _mysql_b_bom_pretreatment.InsertManyAsync(addList); } } /// /// BOM清单批量预处理 /// public void AutoCreateBomBillInterface(string companyid) { AutoCreateBomBill(companyid); } public async Task AutoCreatePickBill(List workOrdMasters, List dbPeriodSequences, List nbrMasterList, List nbrDetailList, string userAccount, List workDetails) { if (dbPeriodSequences.Any()) { List AllLines = dbPeriodSequences.Where(a => workOrdMasters.Select(b=>b.WorkOrd).Contains(a.WorkOrds)).Select(a => a.Line).Distinct().ToList(); List AllLineMasters = _lineMaster.Select(p => AllLines.Contains(p.Line) && p.Domain == workOrdMasters[0].Domain && p.IsActive); var user = _employeeMaster.Select(s => s.Employee == userAccount && s.Domain == workOrdMasters[0].Domain).FirstOrDefault(); var ewdmList = _empWorkDutyMaster.Select(s => s.Domain == workOrdMasters[0].Domain).ToList(); //需要前处理物料 var Items = _mysql_ic_item.GetListAsync(s => workDetails.Select(c => c.ItemNum).Contains(s.number) && s.factory_id.ToString() == workOrdMasters[0].Domain).Result; List itemMasterList = _itemMaster.Select(p => workDetails.Select(c => c.ItemNum).Contains(p.ItemNum) && p.Domain == workOrdMasters[0].Domain).Distinct().ToList(); //按照工单领料,之前是按照排产日期和产线分别领料 foreach (var workord in workOrdMasters) { Dictionary dictItemQty = new Dictionary(); string LocationTo = ""; LineMaster defaultLine = null; var dftPs = dbPeriodSequences.Where(a => a.WorkOrds == workord.WorkOrd).OrderBy(s => s.CreateTime).FirstOrDefault(); if (dftPs != null) { List lineMasters = AllLineMasters.Where(p => p.Line == dftPs.Line && p.Domain == workord.Domain && p.IsActive).ToList(); if (lineMasters.Any()) { defaultLine = lineMasters.FirstOrDefault(); } LocationTo = defaultLine?.VLocation; } var workdtls = workDetails.Where(s => s.WorkOrd == workord.WorkOrd).ToList(); //List itemList = GetProductStructure(dbPeriodSequences.First(a => a.WorkOrds == workord.WorkOrd).ItemNum, QtyOrdSum, workord.Domain); //var childrenList = itemList.Select(a => a.ComponentItem).Distinct().ToList(); List itemLocList = itemMasterList.Where(p => workdtls.Select(c => c.ItemNum).Contains(p.ItemNum) && p.Domain == workord.Domain).Distinct().ToList(); List cleanDetail = new List(); List noCleanDetail = new List(); workdtls.ForEach(s => { var i = Items.Find(x => x.number == s.ItemNum && x.is_clean == 1); if (i != null) { cleanDetail.Add(s); } else { noCleanDetail.Add(s); } }); //获取预处理提前期最大值 decimal cleanTime = 0; if (noCleanDetail.Any()) { //无需前处理领料单 GenerateNbr(workord, cleanTime, defaultLine, userAccount, nbrMasterList, nbrDetailList, noCleanDetail, itemLocList, ewdmList, LocationTo, user,""); } if (cleanDetail.Any()) { //需要前处理的领料单 cleanTime = Items.Where(s=> cleanDetail.Select(i=>i.ItemNum).Contains(s.number)).Max(s => s.clean_leadtime.GetValueOrDefault()); GenerateNbr(workord, cleanTime, defaultLine, userAccount, nbrMasterList, nbrDetailList, cleanDetail, itemLocList, ewdmList, LocationTo, user, "PrevProcess"); } //List itemPackList = _itemPackMaster.Select(p => childrenList.Contains(p.ItemNum) && p.Domain == workord.Domain && p.IsActive).Distinct().ToList(); /*//先屏蔽备料单扣除库存的DEMO演示。 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(); 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.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.WorkOrd).Min(a => a.PlanDate).GetValueOrDefault().AddDays(-7); } //TODO: //因为我们并没有模拟发料的过程,在自动生成领料单的时候就要扣减库存,实际业务不能这么做。 //在有上料和追溯的系统,可以在扫码上料或报工时(从线边仓)扣减。或者在实际发料出库时扣减。 var locStock = _locationDetail.Select(a => itemKeys.Contains(a.ItemNum) && a.IsActive && a.Domain == workOrdMasters[0].Domain); 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);*/ } if (nbrMasterList.Any()) { var nbrlistDto = _serialNumberAppService.GetBillNo(workOrdMasters[0].Domain, "SM", nbrMasterList.Count, userAccount, 1); if (nbrlistDto.Any()) { int index = 0; foreach (var nm in nbrMasterList) { var nbrDtls = nbrDetailList.Where(s => s.Nbr == nm.Nbr).ToList(); if (nbrlistDto[index] != null) { nm.Nbr = nbrlistDto[index].NbrResult; nbrDtls.ForEach(i => { i.Nbr = nm.Nbr; }); } index++; } } } } } private void GenerateNbr(WorkOrdMaster workord,decimal cleanTime, LineMaster defaultLine, string userAccount, List nbrMasterList, List nbrDetailList, List detail, List itemLocList, List ewdmList, string LocationTo,EmployeeMaster user,string TransType) { string Nbr = help.NextId().ToString(); DateTime eff = workord.OrdDate.GetValueOrDefault().Date.AddDays(-1); DateTime start = eff.AddDays((double)(0 - cleanTime)); if (start <= DateTime.Now.Date) { start = DateTime.Now.Date; } var newNbr = new NbrMaster { Domain = workord.Domain, Type = "SM", Nbr = Nbr, Remark = "下达自动领料", //Date = dbPeriodSequences.Where(a => a.WorkOrds == workord.WorkOrd).Min(a => a.PlanDate), ProdLine = defaultLine?.Line, EffDate = eff, Date = start, Status = "", WorkOrd = workord.WorkOrd, QtyOrd = workord.QtyOrded, IsActive = true, IsChanged = true, Name = userAccount, Department = "101", CreateTime = DateTime.Now, UpdateTime = DateTime.Now, CreateUser = user?.Name, UpdateUser = user?.Name, TransType = TransType }; nbrMasterList.Add(newNbr); List headAccount = new List(); int i = 1; bool typed = !string.IsNullOrEmpty(workord.Typed); detail.ForEach(a => { var find = itemLocList?.Find(c => c.ItemNum == a.ItemNum); string LocationFrom = ""; if (find != null) { LocationFrom = find.Location; //找出职责范围负责人 var ewdm = ewdmList.Find(s => 0 >= string.Compare(s.ItemNum1, a.ItemNum) && 0 >= string.Compare(a.ItemNum, s.ItemNum2)); if (ewdm != null && !string.IsNullOrEmpty(ewdm.Employee)) { headAccount.Add(ewdm.Employee); } //相同物料汇总 var itemComponent = nbrDetailList.Find(b => b.Nbr == Nbr && b.ItemNum == a.ItemNum); if (itemComponent == null) { nbrDetailList.Add(new NbrDetail { Domain = workord.Domain, Type = "SM", Nbr = Nbr, ItemNum = a.ItemNum, QtyFrom = 0, QtyTo = 0, LocationFrom = LocationFrom, LocationTo = LocationTo,//现在这几条线是同一线边仓,暂时不考虑多个线边仓 WorkOrd = workord.WorkOrd, QtyOrd = a.QtyRequired, CurrQtyOpened = a.QtyRequired, Line = i, IsActive = true, CreateTime = DateTime.Now, UpdateTime = DateTime.Now, CreateUser = user?.Name, UpdateUser = user?.Name, UM = find.UM, LotSerial = typed ? a.LotSerial : "" }); i++; } else { nbrDetailList.First(b => b.Nbr == Nbr && b.ItemNum == a.ItemNum).QtyOrd = itemComponent.QtyOrd + a.QtyRequired; nbrDetailList.First(b => b.Nbr == Nbr && b.ItemNum == a.ItemNum).CurrQtyOpened = itemComponent.CurrQtyOpened + a.QtyRequired; } } }); if (headAccount.Any()) { newNbr.User1 = string.Join(",", headAccount.Distinct()); string[] user2 = headAccount.ToArray(); newNbr.User2 = JsonConvert.SerializeObject(user2); } } 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 == param.factoryId.ToString() && 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 == param.factoryId && a.company_id == param.company_id).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 == param.factoryId && a.company_id == param.company_id).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 = param.factoryId; stock.company_id = param.company_id; 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; } /// /// 生成领料单 /// /// public async Task CreatePickBill(string workOrd, string domain, string userAccount) { List workOrds = new List(); List workOrdMasters = new List(); if (string.IsNullOrEmpty(workOrd)) { //获取工单数据 workOrdMasters = _workOrdMaster.Select(p => p.Domain == domain && 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 "没有需要下达的工单。"; } workOrdMasters = _workOrdMaster.Select(p => p.Domain == domain && 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 == domain && 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 == domain && 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 "当前选择的工单包含已领料或未排产。"; } //增加判断当前工单是否进行过齐套检查,并且是仓库齐套 /*var mes_morders = _mysql_mes_morder.GetListAsync(s => dbWorkOrds.Contains(s.morder_no) && s.factory_id.ToString() == domain).Result; if (mes_morders.Where(s => s.MaterialSituation != MorderEnum.CarehouseComplete).Any()) { return "请选择物料情况为“仓库齐套”的工单。"; }*/ List nbrMasterList = new List();//需要生成领料单列表 List nbrDetailList = new List();//需要生成领料单明细列表 var ords = workOrdMasters.Select(p => p.WorkOrd).ToList(); var workDetails = _workOrdDetail.Select(p => p.Domain == domain && workOrds.Contains(p.WorkOrd)); dbPeriodSequences = dbPeriodSequences.Where(p => ords.Contains(p.WorkOrds)).ToList(); await AutoCreatePickBill(workOrdMasters, dbPeriodSequences, nbrMasterList, nbrDetailList, userAccount, workDetails); if (nbrMasterList.Any()) { //改到发布日计划时更新。 //dbPeriodSequences.ForEach(p => { p.Status = "r"; }); workOrdMasters.ForEach(p => { p.Status = "r"; }); var nbrlistDto = _serialNumberAppService.GetBillNo(workOrdMasters[0].Domain, "WOlot", workOrdMasters.Count, userAccount, 1); if (nbrlistDto.Any()) { int index = 0; foreach (var nm in nbrMasterList) { var nbrDtls = nbrDetailList.Where(s => s.Nbr == nm.Nbr).ToList(); if (nbrlistDto[index] != null) { nm.Nbr = nbrlistDto[index].NbrResult; nbrDtls.ForEach(i => { i.Nbr = nm.Nbr; }); } index++; } } //清理掉库存占用 这里考虑的是资源检查的占用没有完全占用备料单数据,而其他数据再进行齐套检查时,无法考虑到备料单的占用。 var itemstockoccupy = _mysql_ic_item_stockoccupy.GetListAsync(s => workOrdMasters.Select(x => x.WorkOrd).Contains(s.morder_mo) && s.factory_id.ToString() == domain).Result; var icitem = _mysql_ic_item.GetListAsync(s => s.factory_id.ToString() == domain && nbrDetailList.Select(c => c.ItemNum).Contains(s.number)).Result; //根据领料单生成一次工单的数据占用 List insertOccuyy = new List(); nbrMasterList.ForEach(s => { var nbrdtls = nbrDetailList.Where(a => a.Nbr == s.Nbr).ToList(); nbrdtls.ForEach(x => { ic_item_stockoccupy itemStockoccupyDto = new ic_item_stockoccupy(); itemStockoccupyDto.GenerateNewId(help.NextId()); itemStockoccupyDto.morder_mo = s.WorkOrd; itemStockoccupyDto.occupy_time = DateTime.Now; var nbrItem = icitem.Find(c => c.number == x.ItemNum); if(nbrItem!= null) { itemStockoccupyDto.icitem_id = nbrItem.Id; itemStockoccupyDto.icitem_number = nbrItem.number; itemStockoccupyDto.tenant_id = nbrItem.tenant_id; itemStockoccupyDto.factory_id = nbrItem.factory_id; itemStockoccupyDto.org_id = nbrItem.org_id; itemStockoccupyDto.company_id = nbrItem.company_id; itemStockoccupyDto.quantity = x.CurrQtyOpened.GetValueOrDefault(); insertOccuyy.Add(itemStockoccupyDto); } }); }); //获取工单工艺路径数据 List workOrdRoutings = _workOrdRouting.Select(p => ords.Contains(p.WorkOrd) && p.MilestoneOp && p.Domain == workOrdMasters[0].Domain && 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); }); if (itemstockoccupy.Any()) { await _mysql_ic_item_stockoccupy.HardDeleteAsync(itemstockoccupy); } if (insertOccuyy.Any()) { _businessDbContext.BulkInsert(insertOccuyy); } //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值 List nbrs = nbrMasterList.Select(a => a.Nbr).ToList(); var DBnbrList = _nbrMaster.Select(a => a.Domain == workOrdMasters[0].Domain && 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 "ok"; } /// /// 同步工单等相关数据 /// /// /// 工艺路线数据 public void CreateWorkOrdDates(List morders, List allRoutings, List workOrds, List workOrdRoutings, List workOrdDetails, List exmResult, List childExamineList) { //工单主表 WorkOrdMaster workOrd; //工单工艺路线表 WorkOrdRouting woRouting; //工单物料表 WorkOrdDetail woDetail; foreach (var item in morders) { //添加工单数据 workOrd = new WorkOrdMaster(); workOrd.Domain = item.factory_id.ToString(); workOrd.OrdDate = item.moentry_sys_stime; workOrd.DueDate = item.moentry_sys_etime; 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 = ""; workOrds.Add(workOrd); //添加工单工艺路线数据 var curRoutings = allRoutings.Where(p => p.RoutingCode == item.product_code).ToList(); foreach (var dtl in curRoutings) { woRouting = new WorkOrdRouting(); woRouting.Domain = item.factory_id.ToString(); woRouting.Descr = dtl.Descr; woRouting.MilestoneOp = dtl.MilestoneOp; woRouting.WorkOrd = item.morder_no; woRouting.OP = dtl.Op; woRouting.ParentOp = dtl.ParentOp; woRouting.RunTime = dtl.RunTime; woRouting.ItemNum = item.product_code; woRouting.QtyOrded = item.need_number.GetValueOrDefault(); woRouting.OverlapUnits = dtl.OverlapUnits; woRouting.Status = ""; woRouting.IsActive = true; woRouting.CommentIndex = dtl.CommentIndex; woRouting.CreateTime = DateTime.Now; workOrdRoutings.Add(woRouting); } long fid = GetParentMo(morders, item); var exm = exmResult.Find(s => s.morder_id == fid); if (exm != null) { var childs = childExamineList.Where(s => s.examine_id == exm.Id && s.is_use == true).ToList(); var child = childs.Find(s => s.item_number == item.product_code); if (child == null) { continue; } List returnList = new List(); GetWorkDetalis(childs.Where(s => s.parent_id == child.fid).ToList(), returnList, childs); if (returnList.Any()) { foreach (var structure in returnList) { woDetail = workOrdDetails.Find(s => s.ItemNum == structure.item_number && s.WorkOrd == item.morder_no); if (woDetail == null) { //添加工单的物料信息 woDetail = new WorkOrdDetail(); woDetail.Domain = item.factory_id.ToString(); woDetail.WorkOrd = item.morder_no; woDetail.Op = structure.Op; woDetail.ItemNum = structure.item_number; woDetail.QtyRequired = structure.needCount.GetValueOrDefault(); woDetail.QtyPosted = 0m; woDetail.QtyReturned = 0m; woDetail.FrozenBOMQty = structure.needCount.GetValueOrDefault(); woDetail.Status = ""; woDetail.IsActive = true; woDetail.CreateTime = DateTime.Now; workOrdDetails.Add(woDetail); } else { woDetail.QtyRequired += structure.needCount.GetValueOrDefault(); woDetail.FrozenBOMQty += structure.needCount.GetValueOrDefault(); } } } } /*List curStructures = GetProductStructure(item.product_code, workOrd.QtyOrded, item.factory_id.ToString()); foreach (var structure in curStructures) { woDetail = workOrdDetails.Find(s => s.ItemNum == structure.ComponentItem); if (woDetail == null) { //添加工单的物料信息 woDetail = new WorkOrdDetail(); woDetail.Domain = item.factory_id.ToString(); woDetail.WorkOrd = item.morder_no; woDetail.Op = structure.Op; woDetail.ItemNum = structure.ComponentItem; woDetail.QtyRequired = structure.Qty; woDetail.QtyPosted = 0m; woDetail.QtyReturned = 0m; woDetail.FrozenBOMQty = structure.Qty; woDetail.Status = ""; woDetail.IsActive = true; woDetail.CreateTime = DateTime.Now; workOrdDetails.Add(woDetail); } else { woDetail.QtyRequired += structure.Qty; woDetail.FrozenBOMQty += structure.Qty; } }*/ } } public long GetParentMo(List morders, mes_morder item) { if (item.parent_id != null) { var parentMo = morders.Find(s => s.Id == item.parent_id); if (parentMo != null) { return GetParentMo(morders, parentMo); } else { return item.Id; } } else { return item.Id; } } /// /// 获取虚拟件明细 /// /// /// /// public void GetWorkDetalis(List dtl, List returnList, List childs) { returnList.AddRange(dtl); var rst = childs.Where(s => dtl.Where(x => x.erp_cls == 4).Select(c => c.fid).Contains(s.parent_id.GetValueOrDefault())).ToList(); if (rst.Any()) { GetWorkDetalis(rst, returnList, childs); } return; } /// /// 获取标准Bom数据--TODO:存在循环查询数据库问题,后续调整 /// /// 产品物料编码 /// public List GetProductStructure(string itenNum,decimal QtyOrdSum, string domain) { List rtnStructures = new List(); //根据itemNum获取bom数据 var productStructures = _productStructureMaster.Select(p => itenNum == p.ParentItem && p.Domain == domain && p.IsActive); productStructures.ForEach(s => { s.Qty = s.Qty * QtyOrdSum; }); //添加非虚拟件 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(curPhantoms, rtnStructures); return rtnStructures; } /// /// 递归获取虚拟件的子物料 /// /// 产品的物料编码 /// 当前产品的虚拟件 /// public void RecursionProductStructure(List structures, List rtnStructures) { //获取虚拟件的子物料 List chdStructures = _productStructureMaster.Select(p => structures.Select(m => m.ComponentItem).Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive); chdStructures.ForEach(s => { var parent = structures.Find(x => x.ComponentItem == s.ParentItem); s.Qty = parent.Qty * s.Qty; }); //非虚拟件 var notPhantoms = chdStructures.Where(p => p.StructureType.ToUpper() != "X").ToList(); rtnStructures.AddRange(notPhantoms); //虚拟件 var phantoms = chdStructures.Where(p => p.StructureType.ToUpper() == "X").ToList(); if (phantoms.Count > 0) { //递归 RecursionProductStructure(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); } /// /// 替代方案保存 /// /// /// public async Task SubstituteSave(SubstituteDto dto) { ic_substitute stt; if (dto.id == null) { if (_mysql_ic_substitute.GetListAsync(s => s.substitute_code == dto.scode).Result.Count > 0) { return "已存在【" + dto.scode + "】替代方案。"; } var check = SubstituteSaveBeforCheck(dto); if (check != "ok") { return check; } //新增 stt = new ic_substitute(); stt.GenerateNewId(help.NextId()); stt.substitute_code = dto.scode; stt.substitute_mode = dto.smode; stt.substitute_strategy = dto.sstrategy; stt.create_by = dto.create_by; stt.create_by_name = dto.create_by_name; stt.create_time = DateTime.Now; stt.update_by = dto.create_by; stt.update_by_name = dto.create_by_name; stt.update_time = DateTime.Now; stt.tenant_id = dto.tenant_id; stt.company_id = dto.company_id; stt.factory_id = dto.factory_id; List glist = new List(); List dlist = new List(); SubstituteSaveGenerate(dto, stt, glist, dlist); using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _businessDbContext.BulkInsert(new List { stt }); if (glist.Any()) { _businessDbContext.BulkInsert(glist); } if (dlist.Any()) { _businessDbContext.BulkInsert(dlist); } await unitOfWork.CompleteAsync(); return "ok"; } catch (Exception e) { new NLogHelper("ResourceExamineAppService").WriteLog("SubstituteSave", "替代方案保存失败:" + e.Message, _currentTenant.Id.ToString()); unitOfWork.Dispose(); return "保存失败,请联系管理员。"; } } } else { //修改 stt = _mysql_ic_substitute.FirstAsync(s => s.Id == dto.id.Value).Result; if (stt != null) { if (_mysql_ic_substitute.GetListAsync(s => s.Id != dto.id && s.substitute_code == dto.scode && s.company_id == dto.company_id && s.factory_id == dto.factory_id).Result.Count > 0) { return "已存在【" + dto.scode + "】替代方案。"; } if (_mysql_ic_bom_child.GetListAsync(s => s.substitute_code == stt.substitute_code).Result.Count() > 0) { return "替代方案已被关联使用,不允许修改。"; } var check = SubstituteSaveBeforCheck(dto); if (check != "ok") { return check; } stt.substitute_code = dto.scode; stt.substitute_mode = dto.smode; stt.substitute_strategy = dto.sstrategy; stt.update_by = dto.create_by; stt.update_by_name = dto.create_by_name; stt.update_time = DateTime.Now; List glist = new List(); List dlist = new List(); SubstituteSaveGenerate(dto, stt, glist, dlist); var delgList = _mysql_ic_substitute_group.GetListAsync(s => s.substitute_group_id == stt.Id).Result; var deldList = _mysql_ic_substitute_group_detail.GetListAsync(s => delgList.Select(c => c.Id).Contains(s.substitute_group_id)).Result; using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _businessDbContext.BulkUpdate(new List { stt }); if (delgList.Any()) { await _mysql_ic_substitute_group.HardDeleteAsync(delgList); } if (deldList.Any()) { await _mysql_ic_substitute_group_detail.HardDeleteAsync(deldList); } if (glist.Any()) { _businessDbContext.BulkInsert(glist); } if (dlist.Any()) { _businessDbContext.BulkInsert(dlist); } return "ok"; } catch (Exception e) { new NLogHelper("ResourceExamineAppService").WriteLog("SubstituteSave", "替代方案保存失败:" + e.Message, _currentTenant.Id.ToString()); unitOfWork.Dispose(); return "保存失败,请联系管理员。"; } } } else { return "当前方案已被删除,请刷新重试。"; } } } /// /// 校验 /// /// /// public string SubstituteSaveBeforCheck(SubstituteDto dto) { if (!dto.srows.Any()) { return "替代明细不能为空。"; } if (dto.srows.Where(s => s.field_83817a9f5a15a4f78686105c694b0a39 == "是").Count() == 0) { return "请设置替代方案里的标准件。"; } if (dto.srows.Where(s => s.field_83817a9f5a15a4f78686105c694b0a39 == "否").Count() == 0) { return "请设置替代方案里的替代件。"; } if (dto.srows.Select(s => s.field_f8988ed2955a264f8f762faaed2c5f6a.GetValueOrDefault()).Count() < 2) { return "替代方案最低存在两个优先级。"; } //判断同一个优先级里,相同是否标准料 foreach (var r in dto.srows) { if (dto.srows.Where(s => s.field_f8988ed2955a264f8f762faaed2c5f6a == r.field_f8988ed2955a264f8f762faaed2c5f6a && s.field_83817a9f5a15a4f78686105c694b0a39 != r.field_83817a9f5a15a4f78686105c694b0a39).Count() > 0) { return "同优先级群组里不允许既有标准件又有替代件。"; } } /*if (dto.srows.GroupBy(s => new { s.field_f8988ed2955a264f8f762faaed2c5f6a, s.field_83817a9f5a15a4f78686105c694b0a39 }).Where(g => g.Count() > 1).Count() > 0) { return "同优先级群组里不允许既有标准件又有替代件。"; }*/ return "ok"; } /// /// 组装数据 /// public void SubstituteSaveGenerate(SubstituteDto dto, ic_substitute stt, List glist, List dlist) { dto.srows.ForEach(s => { ic_substitute_group g = glist.Where(x => x.order_num == s.field_f8988ed2955a264f8f762faaed2c5f6a.GetValueOrDefault()).FirstOrDefault(); if (g == null) { g = new ic_substitute_group(); g.GenerateNewId(help.NextId()); g.substitute_group_id = stt.Id; g.substitute_code = stt.substitute_code; g.replace_name = s.substitute_code; g.order_num = s.field_f8988ed2955a264f8f762faaed2c5f6a.GetValueOrDefault(); g.main_material = s.field_83817a9f5a15a4f78686105c694b0a39 == "是" ? 1 : 0; g.update_by = dto.create_by; g.update_by_name = dto.create_by_name; g.update_time = DateTime.Now; g.tenant_id = dto.tenant_id; g.company_id = dto.company_id; g.factory_id = dto.factory_id; glist.Add(g); } ic_substitute_group_detail d = new ic_substitute_group_detail(); d.GenerateNewId(help.NextId()); d.substitute_group_id = g.Id; d.substitute_code = stt.substitute_code; d.icitem_id = s.icitem_id.GetValueOrDefault(); d.icitem_number = s.icitem_number; d.seq = s.seq; d.replace_qty = s.replace_qty; d.update_by = dto.create_by; d.update_by_name = dto.create_by_name; d.update_time = DateTime.Now; d.tenant_id = dto.tenant_id; d.company_id = dto.company_id; d.factory_id = dto.factory_id; dlist.Add(d); }); } /// /// 手动排产接口 /// /// /// /// public async Task ProductionSchedule(string domain) { //获取需要排产的工单(获取四周的工单:正常工单+已审批通过的特殊工单) DateTime endDate = DateTime.Now.Date.AddDays(118).AddDays(1); //取数开始时间为当前天的下一天 DateTime startDate = DateTime.Now.Date.AddDays(1); //尚未开始生产的工单+正在生产的工单 var workOrds = _workOrdMaster.Select(p => p.IsActive && p.Domain == domain && ((p.OrdDate < endDate && p.OrdDate >= startDate && (string.IsNullOrEmpty(p.Typed) || (!string.IsNullOrEmpty(p.Typed) && p.BusinessID > 0))) || p.Status.ToLower() == "w")).ToList(); string result = await _productionScheduleAppService.DoProductSchedule(workOrds, domain, 2); return result; } /// /// 日计划日期调整 /// /// 日计划调整入参 /// /// public async Task UpdatePlanDate(UpdateDto input) { WorkOrdMaster workOrd = _workOrdMaster.Select(p=>p.IsActive && p.Domain == input.domain && p.WorkOrd == input.workord).FirstOrDefault(); if (workOrd == null) { return "NO|工单【"+input.workord+"】不存在,请联系系统管理员!"; } //更新工单计划开工日期,调整是否需要处理提前期状态字段为B workOrd.OrdDate = input.planDate; workOrd.JointTyped = "B"; _workOrdMaster.Update(workOrd); //获取需要排产的工单(获取四周的工单:正常工单+已审批通过的特殊工单) DateTime endDate = DateTime.Now.Date.AddDays(28).AddDays(1); //取数开始时间为当前天的下一天 DateTime startDate = DateTime.Now.Date.AddDays(1); //尚未开始生产的工单+正在生产的工单 var workOrds = _workOrdMaster.Select(p => p.IsActive && p.Domain == input.domain && ((p.OrdDate < endDate && p.OrdDate >= startDate && (string.IsNullOrEmpty(p.Typed) || (!string.IsNullOrEmpty(p.Typed) && p.BusinessID > 0))) || p.Status.ToLower() == "w")).ToList(); //调用优先级计算算法 workOrds = _replenishmentAppService.CalcPriority(workOrds.Select(p=>p.WorkOrd).ToList(), input.domain); //执行排产 string result = await _productionScheduleAppService.DoProductSchedule(workOrds, input.domain, 2); return result; } /// /// BOM关联替代方案 /// /// /// public async Task BindingSubstitute(BindingSubstituteDto dto) { var list = _mysql_ic_bom_child.GetListAsync(s => s.bom_id == dto.id && s.tenant_id == dto.tenant_id && s.company_id == dto.company_id && s.factory_id == dto.factory_id).Result; if (dto.bomDetail.Any()) { list.ForEach(s => { s.substitute_code = ""; s.haveicsubs = 0; }); var codeList = dto.bomDetail.Where(s => string.IsNullOrEmpty(s.substitute_code) == false).Select(x => x.substitute_code).Distinct().ToList(); if (codeList.Any()) { var subGdtls = _mysql_ic_substitute_group.GetListAsync(s => s.tenant_id == dto.tenant_id && s.company_id == dto.company_id && s.factory_id == dto.factory_id && codeList.Contains(s.substitute_code)).Result; var subDetalis = _mysql_ic_substitute_group_detail.GetListAsync(s => s.tenant_id == dto.tenant_id && s.company_id == dto.company_id && s.factory_id == dto.factory_id && codeList.Contains(s.substitute_code)).Result; foreach (var code in codeList) { var g = subGdtls.Find(s => s.substitute_code == code && s.main_material == 1); if (g != null) { var dtls = subDetalis.Where(s => s.substitute_group_id == g.Id).ToList(); foreach (var dtl in dtls) { var l = list.Find(s => s.item_number == dtl.icitem_number && s.qty == dtl.replace_qty); if (l == null) { return "当前替代方案【" + code + "】的标准件未找到相同数量相同物料的BOM明细。"; } if (string.IsNullOrEmpty(l.substitute_code)) { l.haveicsubs = 1; l.substitute_code = code; } else { return "当前替代方案【" + code + "】的标准件【" + l.item_number + "】与替代方案【" + l.substitute_code + "】冲突。"; } } } else { return "当前替代方案【" + code + "】未设置标准件。"; } } } await _mysql_ic_bom_child.UpdateManyAsync(list); } return "ok"; } } }