|
|
@@ -37,6 +37,9 @@ using System.Runtime.CompilerServices;
|
|
|
using MongoDB.Driver;
|
|
|
using Volo.Abp.Validation.Localization;
|
|
|
using Hangfire.Annotations;
|
|
|
+using System.IO.Compression;
|
|
|
+using System.Collections;
|
|
|
+using System.Data.SqlTypes;
|
|
|
|
|
|
namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
@@ -694,11 +697,16 @@ namespace Business.ResourceExamineManagement
|
|
|
var sadl = subdtllist.Where(s => s.substitute_allid == sal.Id).ToList();
|
|
|
foreach (var dtl in sadl)
|
|
|
{
|
|
|
- if (dtl.ismain == 0)
|
|
|
+ if (dtl.ismain != 0)//替代关系里,已经将BOM料当成主料存放于替代群组里了。
|
|
|
{
|
|
|
//递归将替代关系组装出来。
|
|
|
SubstitutePretreatment(sl, sal, dtl, item, returnlist, icitemlist, bomlist, bomchildlist, type);
|
|
|
}
|
|
|
+ else {
|
|
|
+ //将主料赋值上属性
|
|
|
+ var dtlitem = returnlist.Find(s => s.item_id == dtl.icitem_id && s.level == item.level);
|
|
|
+ dtlitem.substitute_all_num = sal.order_num;//群组优先级
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -719,7 +727,6 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <param name="bomchildlist"></param>
|
|
|
public void SubstitutePretreatment(ic_substitute sl, ic_substitute_all sal, ic_substitute_all_dtl dtl, BomChildExamineDto toDto, List<BomChildExamineDto> returnlist, List<ic_item> icitemlist, List<ic_bom> bomlist, List<ic_bom_child> bomchildlist, int type)
|
|
|
{
|
|
|
- //循环生成dtl层级dto,明细
|
|
|
//如果dtl对应的icitem是BOM,还需要向下继续展开。
|
|
|
var help = new SnowFlake();
|
|
|
|
|
|
@@ -743,8 +750,9 @@ namespace Business.ResourceExamineManagement
|
|
|
dto.erp_cls = icitem.erp_cls;
|
|
|
dto.erp_cls_name = icitem.erp_cls_name;
|
|
|
dto.backflush = toDto.backflush;
|
|
|
- dto.qty = toDto.qty;
|
|
|
- dto.replace_amount = dtl.replace_amount.Value;
|
|
|
+ //dto.qty = toDto.qty;
|
|
|
+ //dto.replace_amount = dtl.replace_amount.Value;
|
|
|
+ dto.qty = dtl.replace_amount.Value;
|
|
|
dto.is_replace = 0;
|
|
|
dto.haveicsubs = 0;
|
|
|
dto.substitute_code = "";
|
|
|
@@ -802,10 +810,178 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ public void calcTest(List<BomChildExamineDto> returnlist, long bangid, long orderid)
|
|
|
+ {
|
|
|
+ //占用情况
|
|
|
+ var occupylist = _ic_item_stockoccupy.GetManyByCondition(p => p.icitem_id == bangid && p.order_id == orderid).Result;
|
|
|
+
|
|
|
+ //第一级
|
|
|
+ var childList = returnlist.Where(s => s.parent_id == returnlist[0].id && s.type == 0).ToList();
|
|
|
+ //这是从上往下展开计算缺料和可制
|
|
|
+ calcTest2(returnlist[0], childList, returnlist, occupylist);
|
|
|
+ returnlist[0].kz = childList.Min(s => s.kz);//得到最小可制数量。
|
|
|
+ //再加个循环,来根据替代关系里的检查结果,根据规则明确使用和生成占用关系。
|
|
|
+ foreach (var item in childList)
|
|
|
+ {
|
|
|
+ //提取群组关系
|
|
|
+ var sublist = returnlist.Where(s => s.parent_id == item.parent_id && s.num == item.num && s.level == item.level).OrderBy(c => c.substitute_all_num).ToList();
|
|
|
+ int idx;
|
|
|
+ List<BomChildExamineDto> select = new List<BomChildExamineDto>();
|
|
|
+ switch (item.substitute_strategy)
|
|
|
+ {
|
|
|
+ case 0://整批
|
|
|
+ //循环检查哪一批可以直接使用,不需要采购
|
|
|
+ for (idx = 0; idx < 99; idx++)
|
|
|
+ {
|
|
|
+ var list = sublist.Where(s => s.substitute_all_num == idx).ToList();
|
|
|
+ if (list.Any())
|
|
|
+ {
|
|
|
+ if (list.Where(s => s.stock_state != 1 && s.stock_state != 2 && s.stock_state != 3).Count() == 0)
|
|
|
+ {
|
|
|
+ //只满足充足或可制
|
|
|
+ //无缺料情况
|
|
|
+ select = list;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ idx++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ idx = 99;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //如果都需要采购的情况下,则默认使用优先级最高的
|
|
|
+ if (select.Count() == 0)
|
|
|
+ {
|
|
|
+ //如果为空,则默认使用优先级为0的集合作为替代关系
|
|
|
+ select = sublist.Where(s => s.substitute_all_num == 0).ToList();
|
|
|
+ select.ForEach(s => { s.is_use = true; s.stock_state = 4; });
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 1://混用
|
|
|
+ for (idx = 0; idx < 99; idx++)
|
|
|
+ {
|
|
|
+ var list = sublist.Where(s => s.substitute_all_num == idx).ToList();
|
|
|
+ if (list.Any())
|
|
|
+ {
|
|
|
+ foreach (var hy in list)
|
|
|
+ {
|
|
|
+ //如果自己是可制,并且有子集,则取出自己父级的缺料数量和可制数量,使用掉自己的末级。
|
|
|
+
|
|
|
+ }
|
|
|
+ idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 2://整批加混用
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void calcTest2(BomChildExamineDto parent, List<BomChildExamineDto> bzlist, List<BomChildExamineDto> returnlist, List<ic_item_stockoccupy> sockoccupyList)
|
|
|
+ {
|
|
|
+ //从第二级开始循环
|
|
|
+ foreach (var item in bzlist)
|
|
|
+ {
|
|
|
+ var childList = returnlist.Where(s => s.parent_id == item.id).ToList();
|
|
|
+
|
|
|
+ //存在替代关系
|
|
|
+ if (item.haveicsubs == 1)
|
|
|
+ {
|
|
|
+ //提取群组关系
|
|
|
+ var sublist = returnlist.Where(s => s.parent_id == item.parent_id && s.num == item.num && s.level == item.level).OrderBy(c => c.substitute_all_num).ToList();
|
|
|
+ //循环计算群组,看哪个群组满足要求,然后使用此群组,将群组的库存和子物料占用掉。
|
|
|
+ //计算此次群组是否有符合
|
|
|
+ MaterialCalc(sublist, returnlist, sockoccupyList);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
+ /// 计算
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="sublist"></param>
|
|
|
+ public void MaterialCalc(List<BomChildExamineDto> sublist, List<BomChildExamineDto> returnlist, List<ic_item_stockoccupy> sockoccupyList)
|
|
|
+ {
|
|
|
+ int maxIdx = sublist.Max(s => s.substitute_all_num);
|
|
|
+ for (int i = 0; i <= maxIdx; i++)
|
|
|
+ {
|
|
|
+ var group = sublist.Where(s => s.substitute_all_num == i).ToList();
|
|
|
+ int boolCount = 0;//代表某一颗物料无需采购,可以自制,则集合+1。
|
|
|
+
|
|
|
+ //如果替代料库存不够,但是可制够,则也考虑使用优先级最高
|
|
|
+ foreach (var g in group)
|
|
|
+ {
|
|
|
+ //根据占用情况计算库存
|
|
|
+ Calczykc(g, sockoccupyList);
|
|
|
+ if (g.stock_state != 1)
|
|
|
+ {
|
|
|
+ //判断此料是否BOM,如果是BOM,就考虑自制是否足够,此处递归检查子集
|
|
|
+ var gChildList = returnlist.Where(s => s.parent_id == g.id).ToList();
|
|
|
+ if (gChildList.Count > 0)
|
|
|
+ {
|
|
|
+ calcTest2(g, gChildList, returnlist, sockoccupyList);
|
|
|
+ //如果是自制,则考虑自制够不够
|
|
|
+ if (g.erp_cls == 1)
|
|
|
+ {
|
|
|
+ g.kz = gChildList.Min(s => s.kz);//得到最小可制数量。
|
|
|
+ //todo:如果是群组替代,可制数量应该跟随着主料来,不应该受限于最小可制单元。
|
|
|
+ g.stock_state = gChildList.Max(s => s.stock_state);
|
|
|
+ if (g.lack_qty < g.kz)
|
|
|
+ {
|
|
|
+ g.stock_state = 2;
|
|
|
+ boolCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ g.kz = Math.Floor(g.sqty / g.qty);//自己不是BOM的情况下,算一下自己可制父级可以制造多少个,这个可制只是基于父级BOM才用来运算。
|
|
|
+ //todo:申老师说,如果是苏州工厂,原材料有可能也是自制的。
|
|
|
+ //所以这里在计算时,还可以直接拿缺料数量,去丢给苏州计算方法,得出原材料的库存加可制。
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ boolCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (boolCount == group.Count())
|
|
|
+ {
|
|
|
+ //如果检查集合满足条数与群组里的物料条数相同,则代表这个群组的数量是满足的。
|
|
|
+ group.ForEach(s =>
|
|
|
+ {
|
|
|
+ s.is_show = true;
|
|
|
+ });
|
|
|
+ break;//如果已经找到合适的替代群组关系,并且都不需要采购,则直接不继续检查了。
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //根据每个物料来实时计算占用情况
|
|
|
+ public void Calczykc(BomChildExamineDto item, List<ic_item_stockoccupy> sockoccupyList)
|
|
|
+ {
|
|
|
+ //找到当前物料的占用记录
|
|
|
+ var itemSockoccupy = sockoccupyList.Where(s => s.icitem_id == item.item_id).ToList();
|
|
|
+ //计算库存减去占用
|
|
|
+ item.sqty -= itemSockoccupy.Sum(s => s.quantity);
|
|
|
+ //如果库存
|
|
|
+ item.sqty = item.sqty < 0 ? 0 : item.sqty;
|
|
|
+ //判断缺料数量
|
|
|
+ item.lack_qty = item.needCount - item.sqty;
|
|
|
+ //判断状态
|
|
|
+ item.stock_state = item.lack_qty > 0 ? 0 : 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ #region 替代检查第一版,屏蔽
|
|
|
+ /*/// <summary>
|
|
|
/// 替代关系检查计算
|
|
|
/// </summary>
|
|
|
- public void CalcIcitemSubstitute(List<BomChildExamineDto> returnlist,int count)
|
|
|
+ public void CalcIcitemSubstitute(List<BomChildExamineDto> returnlist, int count)
|
|
|
{
|
|
|
returnlist = returnlist.OrderBy(s => s.num).ToList();
|
|
|
//1.如果主料够的时候,不需要显示替代料的平铺视图,如果主料不够,显示替代料的平铺视图。
|
|
|
@@ -819,7 +995,7 @@ namespace Business.ResourceExamineManagement
|
|
|
foreach (var item in returnlist)
|
|
|
{
|
|
|
//循环平铺整个资源检查的物料库存情况、缺料情况
|
|
|
- CaclMaterialShortage(returnlist,item, count);
|
|
|
+ CaclMaterialShortage(returnlist, item, count);
|
|
|
}
|
|
|
foreach (var item in returnlist)
|
|
|
{
|
|
|
@@ -841,15 +1017,18 @@ namespace Business.ResourceExamineManagement
|
|
|
public void CaclBomChildUseShortage(List<BomChildExamineDto> returnlist, BomChildExamineDto item)
|
|
|
{
|
|
|
//判断是否是BOM,如果是BOM,还需要向下展开
|
|
|
- var bomchild = returnlist.Where(s => s.parent_id == item.id && s.type == 0).ToList();
|
|
|
+ var bomchild = returnlist.Where(s => s.parent_id == item.id).ToList();
|
|
|
if (bomchild.Count > 0)
|
|
|
{
|
|
|
foreach (var child in bomchild)
|
|
|
{
|
|
|
CaclBomChildUseShortage(returnlist, item);
|
|
|
+ //取子级的最高状态
|
|
|
+ item.stock_state = bomchild.Max(s => s.stock_state);
|
|
|
+ item.kitting_time = bomchild.Max(s => s.kitting_time);
|
|
|
}
|
|
|
}
|
|
|
- var tolist = returnlist.Where(s => s.parent_id == item.parent_id && s.num == item.num).ToList();
|
|
|
+ //var tolist = returnlist.Where(s => s.parent_id == item.parent_id && s.num == item.num).ToList();
|
|
|
//有替代关系
|
|
|
if (item.haveicsubs == 1)
|
|
|
{
|
|
|
@@ -859,12 +1038,21 @@ namespace Business.ResourceExamineManagement
|
|
|
//假设子BOM有替代关系,则子BOM的子物料,也是有替代关系存在的,需要展开来看。
|
|
|
//1.假设标准件库存满足,则不计算替代件关系。
|
|
|
//2.如果标准件不满足,则替代件开始计算并展示。
|
|
|
- //注意:不管是否需要替代件,标准件都需要展开。
|
|
|
+ //注意:不管是否需要替代件,标准件都需要展开。没有使用到的物料,定义为无需求。如果子BOM库存足够,则不需要显示子物料和替代关系。
|
|
|
var sublist = returnlist.Where(s => s.parent_id == item.parent_id && s.num == item.num && s.level == item.level).OrderBy(c => c.substitute_all_num).ToList();
|
|
|
//sublist找出当前含替代关系的标准件和替代件。
|
|
|
+ switch (item.substitute_strategy)
|
|
|
+ {
|
|
|
+ case 0://整批
|
|
|
+ break;
|
|
|
+ case 1://混用
|
|
|
+ break;
|
|
|
+ case 2://整批加混用
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
|
|
|
-
|
|
|
+
|
|
|
|
|
|
if (item.substitute_mode == 0)
|
|
|
{
|
|
|
@@ -872,20 +1060,18 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
else {
|
|
|
//取代
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
- else
|
|
|
+ else//无替代关系
|
|
|
{
|
|
|
- //无替代关系
|
|
|
if (item.stock_state==0)
|
|
|
{
|
|
|
item.use_qty = item.needCount;
|
|
|
item.is_show = true;
|
|
|
- item.stock_state = 0;
|
|
|
}
|
|
|
else if (item.stock_state == 1)
|
|
|
{
|
|
|
+ item.use_qty = item.sqty;
|
|
|
// 缺料数量 item.lack_qty
|
|
|
// 使用数量将库存全部使用了 item.use_qty = item.sqty;
|
|
|
if (item.erp_cls == 2 || item.erp_cls == 3)
|
|
|
@@ -895,6 +1081,7 @@ namespace Business.ResourceExamineManagement
|
|
|
//得到单据到货时间。
|
|
|
//todo:初步设置为7天到货期,后期根据实际业务来补充修改。
|
|
|
item.kitting_time = DateTime.Now.AddDays(7);
|
|
|
+ item.stock_state = 2;
|
|
|
}
|
|
|
else if (item.erp_cls == 1)
|
|
|
{
|
|
|
@@ -902,13 +1089,14 @@ namespace Business.ResourceExamineManagement
|
|
|
//调用产能计算,得到物料自制后的齐套时间。
|
|
|
//todo:初步设置为7天完成,等沟通调用方法,来修改此处。
|
|
|
item.kitting_time = DateTime.Now.AddDays(7);
|
|
|
+ item.stock_state = 3;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 平铺物料缺料情况,展示所有主料+替代料的库存情况、缺料情况
|
|
|
+ /// 平铺物料缺料情况,展示所有主料+替代料的库存情况、缺料情况---需要修改成 库存情况、占用情况
|
|
|
/// </summary>
|
|
|
/// <param name="returnlist"></param>
|
|
|
/// <param name="item"></param>
|
|
|
@@ -918,9 +1106,10 @@ namespace Business.ResourceExamineManagement
|
|
|
var parent = returnlist.Find(s => s.id == item.parent_id);
|
|
|
//当前物料总共需要数量
|
|
|
item.needCount = parent.needCount * item.qty;
|
|
|
- item.satisfyNum = item.sqty;//5
|
|
|
+ //当前库存可以满足的数量
|
|
|
+ item.satisfyNum = item.sqty;
|
|
|
+ //总需要数量减去库存量,得出缺料数量
|
|
|
item.lack_qty = item.needCount - item.satisfyNum;
|
|
|
-
|
|
|
//如果不满足,计算子物料,或者计算替代料
|
|
|
if (item.lack_qty < 0)
|
|
|
{
|
|
|
@@ -935,18 +1124,24 @@ namespace Business.ResourceExamineManagement
|
|
|
if (childList.Count > 0)
|
|
|
{
|
|
|
//自己是BOM
|
|
|
+ decimal kz = 0;//当前BOM可制数量
|
|
|
foreach (var child in childList)
|
|
|
{
|
|
|
//循环子集判断库存
|
|
|
CaclMaterialShortage(returnlist, child, count);
|
|
|
+ kz = kz > ((child.sqty+ child.kz) / child.qty) ? Math.Floor((child.sqty + child.kz) / child.qty) : kz;
|
|
|
}
|
|
|
+ //向下取整
|
|
|
+ item.kz =Math.Floor(kz);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
+ //原材料没有可制数量。
|
|
|
+ item.kz = 0;
|
|
|
item.stock_state = 1;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
+ }*/
|
|
|
+ #endregion
|
|
|
}
|
|
|
}
|