|
|
@@ -582,9 +582,6 @@ namespace Business.ResourceExamineManagement
|
|
|
var mesorders = ObjectMapper.Map<List<mo_mes_morder>, List<mes_morder>>(_CalcBomViewAppService.mordersInsertList);
|
|
|
_businessDbContext.BulkInsert(mesorders);
|
|
|
rtn.mordersList = _CalcBomViewAppService.mordersInsertList;
|
|
|
-
|
|
|
- //插入工单相关数据
|
|
|
- CreateWorkOrdDates(_CalcBomViewAppService.mordersInsertList);
|
|
|
}
|
|
|
if (_CalcBomViewAppService.mooccupyAllInsertList.Any())
|
|
|
{
|
|
|
@@ -2017,242 +2014,95 @@ namespace Business.ResourceExamineManagement
|
|
|
AutoCreateBomBill();
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// 同步工单等相关数据
|
|
|
- /// </summary>
|
|
|
- /// <param name="morders"></param>
|
|
|
- [UnitOfWork]
|
|
|
- public void CreateWorkOrdDates(List<mo_mes_morder> morders)
|
|
|
- {
|
|
|
- //获取工艺路线数据:product_code=物料编码
|
|
|
- List<RoutingOpDetail> allRoutings = _routingOpDetail.Select(p => morders.Select(m => m.product_code).Contains(p.RoutingCode));
|
|
|
- //获取标准BOM数据
|
|
|
- List<ProductStructureMaster> productStructures = GetProductStructure(morders.Select(p => p.product_code).ToList());
|
|
|
- //工单主表
|
|
|
- List<WorkOrdMaster> workOrds = new List<WorkOrdMaster>();
|
|
|
- WorkOrdMaster workOrd;
|
|
|
- //工单工艺路线表
|
|
|
- List<WorkOrdRouting> workOrdRoutings = new List<WorkOrdRouting>();
|
|
|
- WorkOrdRouting woRouting;
|
|
|
- //工单物料表
|
|
|
- List<WorkOrdDetail> workOrdDetails = new List<WorkOrdDetail>();
|
|
|
- WorkOrdDetail woDetail;
|
|
|
- foreach (var item in morders)
|
|
|
- {
|
|
|
- //添加工单数据
|
|
|
- workOrd = new WorkOrdMaster();
|
|
|
- workOrd.Domain = "1001";
|
|
|
- workOrd.OrdDate = item.moentry_sys_stime;
|
|
|
- workOrd.ReleaseDate =Convert.ToDateTime(item.moentry_sys_stime.GetValueOrDefault().ToString("u"));
|
|
|
- workOrd.WorkOrd = item.morder_no;
|
|
|
- workOrd.ItemNum = item.product_code;//物料编码
|
|
|
- workOrd.QtyOrded = item.need_number.GetValueOrDefault();
|
|
|
- workOrd.RoutingCode = item.product_code;
|
|
|
- workOrd.Period = 1;
|
|
|
- workOrd.Priority = item.urgent;
|
|
|
- workOrd.Status = "";
|
|
|
- workOrd.IsActive = true;
|
|
|
- workOrd.ProdLine = "组装线";
|
|
|
- workOrd.IsConfirm = true;
|
|
|
- workOrds.Add(workOrd);
|
|
|
-
|
|
|
- //添加工单工艺路线数据
|
|
|
- var curRoutings = allRoutings.Where(p => p.RoutingCode == item.product_code).ToList();
|
|
|
- foreach (var dtl in curRoutings)
|
|
|
- {
|
|
|
- woRouting = new WorkOrdRouting();
|
|
|
- woRouting.Domain = "1001";
|
|
|
- woRouting.Descr = dtl.Descr;
|
|
|
- woRouting.MilestoneOp = dtl.MilestoneOp;
|
|
|
- woRouting.WorkOrd = item.morder_no;
|
|
|
- woRouting.OP = dtl.Op;
|
|
|
- woRouting.ParentOp = dtl.ParentOp;
|
|
|
- woRouting.RunTime = dtl.RunTime;
|
|
|
- woRouting.ItemNum = item.product_code;
|
|
|
- woRouting.QtyOrded = item.need_number.GetValueOrDefault();
|
|
|
- woRouting.OverlapUnits = dtl.OverlapUnits;
|
|
|
- woRouting.Status = "";
|
|
|
- woRouting.IsActive = true;
|
|
|
- workOrdRoutings.Add(woRouting);
|
|
|
- }
|
|
|
-
|
|
|
- //添加工单物料数据
|
|
|
- var curStructures = productStructures.Where(p => p.ParentItem == item.product_code).ToList();
|
|
|
- foreach (var structure in curStructures)
|
|
|
- {
|
|
|
- //添加工单的物料信息
|
|
|
- woDetail = new WorkOrdDetail();
|
|
|
- woDetail.Domain = "1001";
|
|
|
- woDetail.WorkOrd = item.morder_no;
|
|
|
- woDetail.Op = structure.Op;
|
|
|
- woDetail.ItemNum = structure.ComponentItem;
|
|
|
- woDetail.QtyRequired = item.need_number.GetValueOrDefault() * structure.Qty;
|
|
|
- woDetail.QtyPosted = 0m;
|
|
|
- woDetail.QtyReturned = 0m;
|
|
|
- woDetail.Status = "";
|
|
|
- woDetail.IsActive = true;
|
|
|
- workOrdDetails.Add(woDetail);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //await _businessDbContext.BulkInsertAsync(workOrds);
|
|
|
- //await _businessDbContext.BulkInsertAsync(workOrdRoutings);
|
|
|
- //await _businessDbContext.BulkInsertAsync(workOrdDetails);
|
|
|
- _workOrdMaster.Insert(workOrds);
|
|
|
- _workOrdRouting.Insert(workOrdRoutings);
|
|
|
- _workOrdDetail.Insert(workOrdDetails);
|
|
|
-
|
|
|
- //排产
|
|
|
- _productionScheduleAppService.DoProductShcedule(workOrds);
|
|
|
- AutoCreatePickBill(workOrds.Select(a => a.WorkOrd).ToList());
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 获取标准Bom数据--TODO:存在循环查询数据库问题,后续调整
|
|
|
- /// </summary>
|
|
|
- /// <param name="itenNums">产品物料编码</param>
|
|
|
- /// <returns></returns>
|
|
|
- public List<ProductStructureMaster> GetProductStructure(List<string> itenNums)
|
|
|
- {
|
|
|
- List<ProductStructureMaster> rtnStructures = new List<ProductStructureMaster>();
|
|
|
- //根据itemNum获取bom数据
|
|
|
- var productStructures = _productStructureMaster.Select(p => itenNums.Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive);
|
|
|
- //添加非虚拟件
|
|
|
- rtnStructures.AddRange(productStructures.Where(p => p.StructureType.ToUpper() != "X").ToList());
|
|
|
- foreach (var item in itenNums)
|
|
|
- {
|
|
|
- //获取当前产品的虚拟件
|
|
|
- var curPhantoms = productStructures.Where(p => p.ParentItem == item && p.StructureType.ToUpper() == "X").ToList();
|
|
|
- if (curPhantoms.Count() == 0)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
- //递归获取所有虚拟件对应的子物料
|
|
|
- RecursionProductStructure(item, curPhantoms, rtnStructures);
|
|
|
- }
|
|
|
- return rtnStructures;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 递归获取虚拟件的子物料
|
|
|
- /// </summary>
|
|
|
- /// <param name="parentItem">产品的物料编码</param>
|
|
|
- /// <param name="structures">当前产品的虚拟件</param>
|
|
|
- /// <param name="rtnStructures"></param>
|
|
|
- public void RecursionProductStructure(string parentItem, List<ProductStructureMaster> structures, List<ProductStructureMaster> rtnStructures)
|
|
|
- {
|
|
|
- //获取虚拟件的子物料
|
|
|
- var chdStructures = _productStructureMaster.Select(p => structures.Select(m => m.ComponentItem).Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive);
|
|
|
- //非虚拟件
|
|
|
- var notPhantoms = chdStructures.Where(p => p.StructureType.ToUpper() != "X").ToList();
|
|
|
- //存在非虚拟件
|
|
|
- if (notPhantoms.Count() > 0)
|
|
|
- {
|
|
|
- notPhantoms.ForEach(p =>
|
|
|
- {
|
|
|
- p.ParentItem = parentItem;
|
|
|
- });
|
|
|
- rtnStructures.AddRange(notPhantoms);
|
|
|
- }
|
|
|
- //虚拟件
|
|
|
- var phantoms = chdStructures.Where(p => p.StructureType.ToUpper() == "X").ToList();
|
|
|
- if (phantoms.Count() > 0)
|
|
|
- {
|
|
|
- //递归
|
|
|
- RecursionProductStructure(parentItem, phantoms, rtnStructures);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- public void AutoCreatePickBill(List<string> workOrds)
|
|
|
- {
|
|
|
- //获取生产周期数据
|
|
|
- List<PeriodSequenceDet> dbPeriodSequences = _periodSequenceDet.Select(p => workOrds.Contains(p.WorkOrds) && p.Domain == "1001" && p.IsActive);
|
|
|
- List<LineMaster> lineMasters = new List<LineMaster>();
|
|
|
- List<string> lines = new List<string>();//产线列表,
|
|
|
- List<NbrMaster> nbrMasterList = new List<NbrMaster>();//需要生成领料单列表
|
|
|
- List<NbrDetail> nbrDetailList = new List<NbrDetail>();//需要生成领料单明细列表
|
|
|
- Dictionary<string, decimal> dictItemQty = new Dictionary<string, decimal>();
|
|
|
- if (dbPeriodSequences.Any())
|
|
|
- {
|
|
|
- lines = dbPeriodSequences.Select(a => a.Line).Distinct().ToList();
|
|
|
- lineMasters = _lineMaster.Select(p => lines.Contains(p.Line) && p.Domain == "1001" && p.IsActive);
|
|
|
- List<ProductStructureMaster> itemList=GetProductStructure(dbPeriodSequences.Select(a=>a.ItemNum).Distinct().ToList());
|
|
|
- var childrenList= itemList.Select(a=>a.ComponentItem).Distinct().ToList();
|
|
|
- List<ItemMaster> itemLocList = _itemMaster.Select(p => childrenList.Contains(p.ItemNum) && p.Domain == "1001" && p.IsActive).Distinct().ToList();
|
|
|
- foreach (var item in dbPeriodSequences)
|
|
|
- {
|
|
|
- var Nbr = GetMaxSerialNumber(417416915624005);
|
|
|
- nbrMasterList.Add(new NbrMaster
|
|
|
- {
|
|
|
- Domain = "1001",
|
|
|
- Type = "SM",
|
|
|
- Nbr = Nbr,
|
|
|
- Remark = "",
|
|
|
- Date = item.PlanDate,
|
|
|
- ProdLine = item.Line,
|
|
|
- Status = "",
|
|
|
- WorkOrd = item.WorkOrds,
|
|
|
- QtyOrd = item.OrdQty.HasValue ? item.OrdQty.Value : 0,
|
|
|
- IsActive = true,
|
|
|
- IsChanged = false
|
|
|
- });
|
|
|
- int i = 1;
|
|
|
- itemList.Where(a => a.ParentItem == item.ItemNum).ToList()?.ForEach(a =>
|
|
|
- {
|
|
|
- string LocationTo = "";
|
|
|
- if (itemLocList.Where(c => c.ItemNum == a.ComponentItem).ToList().Any())
|
|
|
- {
|
|
|
- LocationTo = itemLocList?.Where(c => c.ItemNum == a.ComponentItem).First().Location;
|
|
|
- }
|
|
|
- nbrDetailList.Add(new NbrDetail
|
|
|
- {
|
|
|
- Domain = "1001",
|
|
|
- Type = "SM",
|
|
|
- Nbr = Nbr,
|
|
|
- ItemNum = a.ComponentItem,
|
|
|
- QtyFrom = 0,
|
|
|
- QtyTo = 0,
|
|
|
- LocationFrom = LocationTo,
|
|
|
- LocationTo = "",
|
|
|
- WorkOrd = item.WorkOrds,
|
|
|
- QtyOrd = item.OrdQty * a.Qty,
|
|
|
- Line = i,
|
|
|
- IsActive = true,
|
|
|
- });
|
|
|
- if(dictItemQty.ContainsKey(a.ComponentItem))
|
|
|
- {
|
|
|
- dictItemQty[a.ComponentItem] = dictItemQty[a.ComponentItem] + item.OrdQty.Value * a.Qty;
|
|
|
- }else
|
|
|
- {
|
|
|
- dictItemQty.Add(a.ComponentItem, item.OrdQty.Value * a.Qty);
|
|
|
- }
|
|
|
- i++;
|
|
|
- });
|
|
|
- }
|
|
|
- _nbrMaster.Insert(nbrMasterList);
|
|
|
- //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值
|
|
|
- List<string> nbrs= nbrMasterList.Select(a=>a.Nbr).ToList();
|
|
|
- var nbrList= _nbrMaster.Select(a => a.Domain == "1001" && a.Type == "SM" && nbrs.Contains(a.Nbr));
|
|
|
- nbrDetailList.ForEach(c =>
|
|
|
- {
|
|
|
- c.NbrRecID= nbrList.Where(a=>a.Nbr==c.Nbr).First().RecID;
|
|
|
- });
|
|
|
- _nbrDetail.Insert(nbrDetailList);
|
|
|
- //TODO:
|
|
|
- //因为我们并没有模拟发料的过程,在自动生成领料单的时候就要扣减库存,实际业务不能这么做。
|
|
|
- //在有上料和追溯的系统,可以在扫码上料或报工时(从线边仓)扣减。或者在实际发料出库时扣减。
|
|
|
- List<string> itemKeys= dictItemQty.Keys.ToList();
|
|
|
- var items=_mysql_ic_item.GetListAsync(a => itemKeys.Contains(a.number) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
- var itemIds=items.Select(b => b.Id).ToList();
|
|
|
- var stockList=_mysql_ic_item_stock.GetListAsync(a => itemIds.Contains(a.Id) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
- stockList?.ForEach(a =>
|
|
|
- {
|
|
|
- a.sqty = a.sqty - dictItemQty[items.First(b => b.Id == a.Id).number];
|
|
|
- });
|
|
|
- //_mysql_ic_item_stock.UpdateManyAsync(stockList);
|
|
|
- }
|
|
|
- }
|
|
|
+ //public void AutoCreatePickBill(List<string> workOrds)
|
|
|
+ //{
|
|
|
+ // //获取生产周期数据
|
|
|
+ // List<PeriodSequenceDet> dbPeriodSequences = _periodSequenceDet.Select(p => workOrds.Contains(p.WorkOrds) && p.Domain == "1001" && p.IsActive);
|
|
|
+ // List<LineMaster> lineMasters = new List<LineMaster>();
|
|
|
+ // List<string> lines = new List<string>();//产线列表,
|
|
|
+ // List<NbrMaster> nbrMasterList = new List<NbrMaster>();//需要生成领料单列表
|
|
|
+ // List<NbrDetail> nbrDetailList = new List<NbrDetail>();//需要生成领料单明细列表
|
|
|
+ // Dictionary<string, decimal> dictItemQty = new Dictionary<string, decimal>();
|
|
|
+ // if (dbPeriodSequences.Any())
|
|
|
+ // {
|
|
|
+ // lines = dbPeriodSequences.Select(a => a.Line).Distinct().ToList();
|
|
|
+ // lineMasters = _lineMaster.Select(p => lines.Contains(p.Line) && p.Domain == "1001" && p.IsActive);
|
|
|
+ // List<ProductStructureMaster> itemList=GetProductStructure(dbPeriodSequences.Select(a=>a.ItemNum).Distinct().ToList());
|
|
|
+ // var childrenList= itemList.Select(a=>a.ComponentItem).Distinct().ToList();
|
|
|
+ // List<ItemMaster> itemLocList = _itemMaster.Select(p => childrenList.Contains(p.ItemNum) && p.Domain == "1001" && p.IsActive).Distinct().ToList();
|
|
|
+ // foreach (var item in dbPeriodSequences)
|
|
|
+ // {
|
|
|
+ // var Nbr = GetMaxSerialNumber(417416915624005);
|
|
|
+ // nbrMasterList.Add(new NbrMaster
|
|
|
+ // {
|
|
|
+ // Domain = "1001",
|
|
|
+ // Type = "SM",
|
|
|
+ // Nbr = Nbr,
|
|
|
+ // Remark = "",
|
|
|
+ // Date = item.PlanDate,
|
|
|
+ // ProdLine = item.Line,
|
|
|
+ // Status = "",
|
|
|
+ // WorkOrd = item.WorkOrds,
|
|
|
+ // QtyOrd = item.OrdQty.HasValue ? item.OrdQty.Value : 0,
|
|
|
+ // IsActive = true,
|
|
|
+ // IsChanged = false
|
|
|
+ // });
|
|
|
+ // int i = 1;
|
|
|
+ // itemList.Where(a => a.ParentItem == item.ItemNum).ToList()?.ForEach(a =>
|
|
|
+ // {
|
|
|
+ // string LocationTo = "";
|
|
|
+ // if (itemLocList.Where(c => c.ItemNum == a.ComponentItem).ToList().Any())
|
|
|
+ // {
|
|
|
+ // LocationTo = itemLocList?.Where(c => c.ItemNum == a.ComponentItem).First().Location;
|
|
|
+ // }
|
|
|
+ // nbrDetailList.Add(new NbrDetail
|
|
|
+ // {
|
|
|
+ // Domain = "1001",
|
|
|
+ // Type = "SM",
|
|
|
+ // Nbr = Nbr,
|
|
|
+ // ItemNum = a.ComponentItem,
|
|
|
+ // QtyFrom = 0,
|
|
|
+ // QtyTo = 0,
|
|
|
+ // LocationFrom = LocationTo,
|
|
|
+ // LocationTo = "",
|
|
|
+ // WorkOrd = item.WorkOrds,
|
|
|
+ // QtyOrd = item.OrdQty * a.Qty,
|
|
|
+ // Line = i,
|
|
|
+ // IsActive = true,
|
|
|
+ // });
|
|
|
+ // if(dictItemQty.ContainsKey(a.ComponentItem))
|
|
|
+ // {
|
|
|
+ // dictItemQty[a.ComponentItem] = dictItemQty[a.ComponentItem] + item.OrdQty.Value * a.Qty;
|
|
|
+ // }else
|
|
|
+ // {
|
|
|
+ // dictItemQty.Add(a.ComponentItem, item.OrdQty.Value * a.Qty);
|
|
|
+ // }
|
|
|
+ // i++;
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ // _nbrMaster.Insert(nbrMasterList);
|
|
|
+ // //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值
|
|
|
+ // List<string> nbrs= nbrMasterList.Select(a=>a.Nbr).ToList();
|
|
|
+ // var nbrList= _nbrMaster.Select(a => a.Domain == "1001" && a.Type == "SM" && nbrs.Contains(a.Nbr));
|
|
|
+ // nbrDetailList.ForEach(c =>
|
|
|
+ // {
|
|
|
+ // c.NbrRecID= nbrList.Where(a=>a.Nbr==c.Nbr).First().RecID;
|
|
|
+ // });
|
|
|
+ // _nbrDetail.Insert(nbrDetailList);
|
|
|
+ // //TODO:
|
|
|
+ // //因为我们并没有模拟发料的过程,在自动生成领料单的时候就要扣减库存,实际业务不能这么做。
|
|
|
+ // //在有上料和追溯的系统,可以在扫码上料或报工时(从线边仓)扣减。或者在实际发料出库时扣减。
|
|
|
+ // List<string> itemKeys= dictItemQty.Keys.ToList();
|
|
|
+ // var items=_mysql_ic_item.GetListAsync(a => itemKeys.Contains(a.number) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
+ // var itemIds=items.Select(b => b.Id).ToList();
|
|
|
+ // var stockList=_mysql_ic_item_stock.GetListAsync(a => itemIds.Contains(a.Id) && a.factory_id == 1001 && a.tenant_id == 1000).Result;
|
|
|
+ // stockList?.ForEach(a =>
|
|
|
+ // {
|
|
|
+ // a.sqty = a.sqty - dictItemQty[items.First(b => b.Id == a.Id).number];
|
|
|
+ // });
|
|
|
+ // //_mysql_ic_item_stock.UpdateManyAsync(stockList);
|
|
|
+ // }
|
|
|
+ //}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 得到一个流水号的最大流水号
|