using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using NetTopologySuite.Geometries; using Omu.ValueInjecter; using Volo.Abp; using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; using Win_in.Sfs.Basedata.Boms; using Win_in.Sfs.Basedata.Domain.Shared; using Win_in.Sfs.Shared.Domain; using Win_in.Sfs.Shared.Domain.Shared; namespace Win_in.Sfs.Basedata.Domain; public class BomManager : DomainService, IBomManager { private readonly IBomRepository _repository; private readonly IItemBasicRepository _itemBasicRepository; public BomManager(IBomRepository repository, IItemBasicRepository itemBasicRepository) { _repository = repository; _itemBasicRepository = itemBasicRepository; } /// /// 获取对应的Bom信息 /// /// /// /// /// public virtual async Task> GetRecursiveListAsync(string productItemCode, DateTime validTime, bool isRecursive = true) { List totalBoms = new List(); var boms = await _repository.GetListAsync(p => p.Product == productItemCode && (p.BeginTime <= validTime) && (p.EndTime >= validTime)).ConfigureAwait(false); if (isRecursive) { foreach (var bom in boms) { if (bom.Component == bom.Product) { totalBoms.AddRange(boms); continue; } //获取下级Bom,如果有就继续,没有就完事 await GetListWithValidTimeAsync(totalBoms, bom, validTime, 1).ConfigureAwait(false); } } else { foreach (var bom in boms) { var item = await _itemBasicRepository.FindAsync(p => p.Code == bom.Component).ConfigureAwait(false); if (item is { IsPhantom: true }) { await GetRecursiveListAsync(bom.Component, validTime, isRecursive).ConfigureAwait(false); } else { totalBoms.Add(bom); }; } } return totalBoms; } /// /// 递归获取bom /// /// /// /// /// /// private async Task GetListWithValidTimeAsync(List totalBoms, Bom bom, DateTime validTime, decimal multipleQty) { var subboms = await _repository.GetListAsync(p => p.Product == bom.Product && p.BeginTime <= validTime && p.EndTime >= validTime).ConfigureAwait(false); if (subboms == null || subboms.Count == 0) { //根据bom多层放大倍数,第一次传过来的是1 bom.ComponentQty *= multipleQty; totalBoms.Add(bom); return; } else { foreach (var subbom in subboms) { //获取下级Bom,如果有就继续,没有就完事 await GetListWithValidTimeAsync(totalBoms, subbom, validTime, subbom.ComponentQty * multipleQty).ConfigureAwait(false); } } } /// /// 执行导入 /// public virtual async Task ImportDataAsync(List mergeEntities, List deleteEntities = null) { if (deleteEntities != null && deleteEntities.Count > 0) { await _repository.BulkDeleteAsync(deleteEntities).ConfigureAwait(false); } await _repository.BulkMergeAsync(mergeEntities).ConfigureAwait(false); } /// /// 所有子物料号 /// /// /// public virtual async Task> GetListOfProductAsync(string product) { return await _repository.GetListAsync(p => p.Product == product).ConfigureAwait(false); } public virtual async Task> GetListWithPhantomItemAsync(string productItemCode, string mfgOp, DateTime validTime, bool onlyFromProductionPlan) { var where = BuildExpression(productItemCode, mfgOp, validTime, onlyFromProductionPlan); var entities = await (await _repository.GetDbSetAsync().ConfigureAwait(false)).AsNoTracking().Where(where).ToListAsync().ConfigureAwait(false); var phantomItemBoms = await GetPhantomItemBomsAsync(entities, mfgOp, validTime, onlyFromProductionPlan).ConfigureAwait(false); return phantomItemBoms; } private static Expression> BuildExpression(string productItemCode, string mfgOp, DateTime validTime, bool onlyFromProductionPlan) { Expression> where = p => p.Product == productItemCode // && p.MFGOp == mfgOp && p.ComponentQty > 0 && (p.BeginTime <= validTime) && (p.EndTime >= validTime); if (onlyFromProductionPlan) { where = where.And(p => p.DistributionType == EnumDistributionType.FromProductionPlan); } return where; } private async Task> GetPhantomItemBomsAsync(List productBoms, string mfgOp, DateTime validTime, bool onlyFromProductionPlan) { var result = new List(); foreach (var bom in productBoms) { var item = await _itemBasicRepository.FirstOrDefaultAsync(p => p.Code == bom.Component).ConfigureAwait(false); if (item == null) { throw new UserFriendlyException($"代码为 {bom.Component} 的物品信息不存在."); } if (item.IsPhantom) { var where = BuildExpression(item.Code, mfgOp, validTime, onlyFromProductionPlan); var query = (await _repository.GetDbSetAsync().ConfigureAwait(false)).AsNoTracking().Where(where); Console.WriteLine(query.ToString()); var phantomItemBoms = await query.ToListAsync().ConfigureAwait(false); //递归获取下层BOM的子零件为虚零件的BOM var nextLevelBoms = await GetPhantomItemBomsAsync(phantomItemBoms, mfgOp, validTime, onlyFromProductionPlan).ConfigureAwait(false); result.AddRange(nextLevelBoms); } else { result.Add(bom); } } return result; } /// /// 所有父物料号 /// /// /// public virtual async Task> GetListOfComponentAsync(string component) { return await _repository.GetListAsync(p => p.Component == component).ConfigureAwait(false); } /// /// 根据总成号、总成数量取所有子物料及其汇总数量 /// /// 总成号 /// 总成数量 /// public virtual async Task> GetMaterialTotalQtyAsync(string productCode, int productNum) { if (productNum < 1) { throw new UserFriendlyException("productNum参数值必须大于等于1"); } var lst = await _repository.GetListAsync(p => p.Product == productCode).ConfigureAwait(false); foreach (var item in lst) { item.ComponentQty = item.ComponentQty * productNum; } return lst; } /// /// Bom操作 /// /// /// /// private async Task> GetSubcomponentsRecursiveLast(BomComponent p_component, EnumBomSelectedType p_type ) { List lastList = new List(); List dimensionList=new List(); var treeList=await GetSubcomponentsRecursive(p_component, 1, p_component.ComponentQty, p_component.Component, (rs) => lastList.Add(rs) , (rs1)=>{ dimensionList.Add(rs1); }).ConfigureAwait(false); List lastBomList = new List(); List dimensionBomList = new List(); List treeBomList = new List(); foreach (var itm in dimensionList) { Bom bom = new Bom(); bom.InjectFrom(itm); dimensionBomList.Add(bom); } foreach (var itm in lastList) { Bom bom = new Bom(); bom.InjectFrom(itm); lastBomList.Add(bom); } foreach (var itm in treeList) { Bom bom = new Bom(); bom.InjectFrom(itm); treeBomList.Add(bom); } List returnList=new List(); switch (p_type) { case EnumBomSelectedType.Last: returnList.AddRange(lastBomList); break; case EnumBomSelectedType.Tree: returnList.AddRange(treeBomList); break; case EnumBomSelectedType.Dimension: returnList.AddRange(dimensionBomList); break; } return returnList; } /// /// 层级、拆解、一维结构、树状结构 /// /// 上级组件(初始时为根元素) /// 层级一般为1 /// 累计数量 /// 根 /// 拆解到最终零件时 /// 树型转成一维表用 /// private async Task> GetSubcomponentsRecursive(BomComponent p_component, int level, decimal sumQty, string root, Action p_actionLast, Action p_actionDimension ) { List subComponents = new List(); // 假设 GetComponentsByProduct 方法可获取某个物料号下的所有子零件 List directSubComponents =await GetComponentsByProduct(p_component.Component).ConfigureAwait(false); if (!directSubComponents.Any() && level != 1)//不是根元素 { p_actionLast(p_component); } foreach (var component in directSubComponents) { component.Root = root; component.SumQty = sumQty * component.ComponentQty; component.ParentComponent = p_component.Component; component.Level = level; component.SubComponents =await GetSubcomponentsRecursive(component, level + 1, sumQty * component.ComponentQty, component.Root, p_actionLast, p_actionDimension).ConfigureAwait(false); p_actionDimension(component); subComponents.Add(component); } return subComponents; } private async Task> GetComponentsByProduct(string product) { var list= await _repository.GetListAsync(p => p.Product == product).ConfigureAwait(false); List components = new List(); foreach (var component in list) { BomComponent bomComponent = new BomComponent(); bomComponent.InjectFrom(component); components.Add(bomComponent); } // 其他物料号的子零件信息类似添加 return components; } }