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.Caches;
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;
InitBomComponent();
}
private void InitBomComponent()
{
int count = _repository.CountAsync().Result;
if (Cache.Boms.Count!=count)
{
Cache.Boms=_repository.ToListAsync().Result;
}
}
///
/// 获取对应的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;
}
public async Task> GetSubcomponentsRecursiveList(List p_lst, EnumBomSelectedType p_type
)
{
List list = new List();
foreach (var item in p_lst)
{
var sublist= await GetSubcomponentsRecursive(item, p_type).ConfigureAwait(false);
list.AddRange(sublist);
}
return list;
}
///
/// Bom操作
///
///
///
///
public async Task> GetSubcomponentsRecursive(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 returnList=new List();
switch (p_type)
{
case EnumBomSelectedType.Last:
returnList = lastList;
break;
case EnumBomSelectedType.Tree:
returnList=treeList;
break;
case EnumBomSelectedType.Dimension:
returnList=dimensionList;
break;
}
return returnList;
}
///
/// 层级、拆解、一维结构、树状结构
///
/// 上级组件(初始时为根元素)
/// 层级一般为1
/// 累计数量
/// 根
/// 拆解到最终零件时
/// 树型转成一维表用
///
///
private async Task> GetSubcomponentsRecursive(BomComponent p_component, int level, decimal sumQty, string root, Action p_actionLast,
Action p_actionDimension
/* ,List bomList =null*/
)
{
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.Path = (p_component.Component != root) ? p_component.Path + $"->{component.Component}" : p_component.Component + $"->{component.Component}";
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)
{
List list=new List();
if (Cache.Boms.Count == 0)
{
InitBomComponent();
}
list=Cache.Boms.Count > 0 ? Cache.Boms.Where(p => p.Product == product).ToList() :
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;
}
///
/// 获取所有bomtree
///
///
///
public virtual async Task> GetAllItemByCode(string productCode)
{
List boms = new List();
var lst = await _repository.GetListAsync(p => p.Product == productCode).ConfigureAwait(false);
foreach (var bom in lst)
{
boms.Add(bom);
var results= await GetAllItemByCode(bom.Component).ConfigureAwait(false);
boms.AddRange(results);
}
return boms;
}
}