using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WMS.Core._02Entity; using WMS.Core._02Entity.FeiXu; using WMS.Info; using WMS.Info.Dto; using WMS.Util; namespace WMS.Core.ServiceCore { public class FxStockOutOrderCore { /// /// 获取分页数据 /// /// public IEnumerable GetStockOutOrderPageList(Pagination pagination, string queryJson) { SqlSugarClient client = null; try { client = SysDbCore.GetDbCtx(); int count = 0; var queryParam = queryJson.ToJObject(); var db = client.Queryable().Where(ord => ord.F_isDelete == 0); //单据日期 if (!queryParam["Btime"].IsEmpty() && !queryParam["Etime"].IsEmpty()) { db.Where(ord => ord.F_addTime >= queryParam["Btime"].ToDate() && ord.F_addTime <= queryParam["Etime"].ToDate()); } if (!queryParam["keyword"].IsEmpty()) { string kw = queryParam["keyword"].ToString(); db.Where(ord => ord.F_no.Contains(kw) || ord.F_relatedOrderNo.Contains(kw)); } if (pagination.sord.ToUpper() != "ASC") { pagination.sidx = pagination.sidx + " DESC"; } var list = db.OrderBy(pagination.sidx).Select(@" [F_warehouseNo], [F_no], [F_relatedOrderNo], [F_totalOrderLines], [F_orderType], [F_orderStatus], [F_memo], [F_addTime], [F_addUserNo], [F_editTime], [F_editUserNo], [F_canceledTime], [F_canceledUserNo], [F_canceledReason], [F_ISDELETE]").ToPageList(pagination.page, pagination.rows, ref count); pagination.records = count; return list; } catch (Exception ex) { throw ex; } finally { client.Dispose(); } } /// /// 获取单据数据 /// /// public IEnumerable GeSockOutOrderItem(string OrderNo) { try { var lst = SysDbCore.GetDbCtx().Queryable().Where(it => it.F_pNo == OrderNo); var list = lst.Select(@" [F_rowNo], [F_pNo], [F_warehouseNo], [F_orderLineNo], [F_matNo], [F_matName], [F_matType], [F_planQty], [F_actualQty], [F_batchNo], [F_unit], [F_addTime], [F_addUserNo], [F_editTime], [F_editUserNo] ").ToList(); return list; } catch (Exception ex) { throw ex; } } /// /// 获取单据数据 /// /// public dynamic GetAssignFormData(string pNo) { try { var lst = SysDbCore.GetDbCtx().SqlQueryable($@"SELECT ord.F_no,ord.F_relatedOrderNo,SUM(line.F_planQty) planSum,SUM(line.F_actualQty) actualSum FROM dbo.BILL_STOCKOUT ord JOIN dbo.BILL_STOCKOUTLINE line ON ord.F_no=line.F_pNo WHERE ord.F_no='{pNo}' GROUP BY ord.F_no,ord.F_relatedOrderNo"); return lst.First(); } catch (Exception ex) { throw ex; } } /// /// 获取实际出库数据 /// /// public IEnumerable GetStockOutDetail(string pNo, string keyword) { try { var lst = SysDbCore.GetDbCtx().Queryable().Where(w => w.F_pNo == pNo); if (!string.IsNullOrWhiteSpace(keyword)) lst = lst.Where(w => w.F_matNo.Contains(keyword)); var list = lst.Select(@" [F_rowNo], [F_pNo], [F_trayNo], [F_boxNo], [F_locationNo], [F_quantity], [F_addUserNo], [F_addTime], [F_matType], [F_matNo] "); return list.ToList(); } catch (Exception ex) { throw ex; } } public IEnumerable GetMatInventory(string pno) { try { //@" inv.[F_no], // inv.[F_warehouseNo], // inv.[F_matNo], // inv.[F_matName], // inv.[F_matType], // inv.[F_quantity], // inv.[F_lockQty], // inv.[F_trayNo], // inv.[F_batchNo], // inv.[F_memo], // inv.[F_addUserNo], // inv.[F_addTime] " var lst = SysDbCore.GetDbCtx().Queryable((inv, ord) => new object[] { JoinType.Inner, inv.F_matNo == ord.F_matNo && inv.F_matType == ord.F_matType }).Where((inv, ord) => ord.F_pNo == pno && inv.F_quantity > 0); var list = lst.Select((inv, ord) => new BILL_INVENTORY { F_addTime = inv.F_addTime, F_addUserNo = inv.F_addUserNo, F_batchNo = inv.F_batchNo, F_boxNo = inv.F_boxNo, F_editTime = inv.F_editTime, F_editUserNo = inv.F_editUserNo, F_isBonded = inv.F_isBonded, F_matNo = inv.F_matNo, F_matName = inv.F_matName, F_matType = inv.F_matType, F_trayNo = inv.F_trayNo, F_projectNo = inv.F_projectNo, F_quantity = inv.F_quantity }).ToList(); return list; } catch (Exception ex) { throw ex; } } /// /// 作废 /// /// 主键 public void CanelEntity(LoginUserInfo loginUserInfo, string _F_No) { SqlSugarClient client = null; try { client = SysDbCore.GetDbCtx(); var db = client.Queryable().Where(it => it.F_no == _F_No).First(); if (db == null) throw new Exception("出库单不存在"); if (db.F_isDelete == 1) throw new Exception("明细已删除"); if (db.F_orderStatus > 1) throw new Exception("单据已经执行中,不可删除"); db.F_canceledUserNo = loginUserInfo.UserNo; db.F_canceledTime = DateTime.Now; db.F_orderStatus = 6; SysDbCore.GetDbCtx().Updateable(db).UpdateColumns(it => new { it.F_canceledUserNo, it.F_canceledTime, it.F_orderStatus }).ExecuteCommand(); } catch (Exception ex) { throw ex; } } /// /// 保存成品销售出库单 /// /// public void SoSave(List sod_det, LoginUserInfo loginUserInfo) { #region 验证工单 //验证工单 //StringBuilder sb = new StringBuilder(); //sb.Append(@" "); //foreach (var item in fX_Sod) //{ // sb.Append(@""); // sb.Append($@"{item.sod_nbr}"); // sb.Append($@"{item.sod_qty_ord} "); // // // // 10636304 // // 200 // // text // // text // // // // // // 16373107 // // 1000 // // text // // text // // // sb.Append(@""); //} //sb.Append(@" "); //var res = WebServiceCall.callWebService(SysSetCore.GetSysSet().FxWebServiceUrl, "processQdocMessage", sb.ToString()); //if (res.Contains("error")) // throw SysExCore.ThrowFailException("工单验证失败!"); #endregion //同步出库单明细 using (var ctx = SysDbCore.GetDbCtx()) { try { if (ctx.Queryable().Any(c => c.F_relatedOrderNo == sod_det.FirstOrDefault().sod_nbr)) throw SysExCore.ThrowFailException($"工单{sod_det.FirstOrDefault().sod_nbr}已生成出库任务!"); ctx.BeginTran(); var bILL_STOCKOUT = new BILL_STOCKOUT { F_addTime = DateTime.Now, F_addUserNo = loginUserInfo.UserNo, F_no = SerialNumberProvider.Instance.OrderNumber("wms", "CK"), F_orderStatus = (int)EOrderState.New, F_orderType = (int)EStockOutOrderType.StockOutOrderTypeProduct, F_relatedOrderNo = sod_det.FirstOrDefault()?.sod_nbr, F_totalOrderLines = sod_det.Count, F_warehouseNo = SysSetCore.GetSysSet().DefaultWarehouseNo }; ctx.Insertable(bILL_STOCKOUT).ExecuteCommand(); foreach (var orderLine in sod_det) { orderLine.add_time = DateTime.Now; orderLine.add_user_no = loginUserInfo.UserNo; ctx.Insertable(orderLine).ExecuteCommand(); var line = new BILL_STOCKOUTLINE { F_addTime = DateTime.Now, F_actualQty = orderLine.sod_qty_ship, F_planQty = orderLine.sod_qty_ord, F_matNo = orderLine.sod_part, F_matName = CacheFacade.GetMatInfo(orderLine.sod_part, EMatType.Product)?.F_matName, F_matType = (int)EMatType.Product, F_orderLineNo = sod_det.IndexOf(orderLine) + 1, F_pNo = bILL_STOCKOUT.F_no, F_warehouseNo = bILL_STOCKOUT.F_warehouseNo, F_addUserNo = loginUserInfo.UserNo }; ctx.Insertable(line).ExecuteCommand(); } ctx.CommitTran(); } catch (Exception ex) { ctx.RollbackTran(); throw ex; } } } /// /// 指定出库 /// /// /// /// public void AssignCreate(StockOutRequest orderRequest, List lineDetailsRequest, LoginUserInfo LoginUser) { using (var ctx = SysDbCore.GetDbCtx()) { try { var matInfo = ctx.Queryable().Where(c => c.F_pNo == orderRequest.F_no && c.F_matNo == lineDetailsRequest.FirstOrDefault().F_matNo).First(); if (matInfo.F_planQty != lineDetailsRequest.Sum(s => s.F_AssignQty)) SysExCore.ThrowFailException("不允许部分指定!"); ctx.BeginTran(); var tasks = new List(); var dicPort = GetPickPort(ctx, orderRequest.PickPort); foreach (var item in lineDetailsRequest) { var location = ctx.Queryable().First(f => f.F_trayNo == item.F_trayNo && f.F_status == (int)EWareCellState.Stored); if (location == null) throw SysExCore.ThrowFailException($"托盘{item.F_trayNo}货位数据异常!"); ctx.Insertable(new BILL_STOCKOUTLINEDETAIL { F_addTime = DateTime.Now, F_addUserNo = LoginUser.UserNo, F_boxNo = item.F_boxNo, F_locationNo = location.F_no, F_matNo = item.F_matNo, F_matName = item.F_matName, F_matType = item.F_matType, F_pNo = orderRequest.F_no, F_quantity = item.F_AssignQty, F_trayNo = item.F_trayNo, F_projectNo = item.F_projectNo }).ExecuteCommand(); var stockOutLine = ctx.Queryable().Where(c => c.F_matNo == item.F_matNo && c.F_pNo == orderRequest.F_no).First(); ctx.Updateable().SetColumns(it => new BILL_STOCKOUTLINE { F_actualQty = stockOutLine.F_actualQty + item.F_AssignQty, F_editUserNo = LoginUser.UserNo, F_editTime = DateTime.Now, }).Where(w => w.F_rowNo == stockOutLine.F_rowNo).ExecuteCommand(); } //生成托盘任务 var trayGroup = lineDetailsRequest.GroupBy(g => new { g.F_trayNo }).Select(s => new { s.Key.F_trayNo, qty = s.Sum(c => c.F_AssignQty) }).ToList(); trayGroup.ForEach(tray => { var location = ctx.Queryable().First(f => f.F_trayNo == tray.F_trayNo && f.F_status == (int)EWareCellState.Stored); var task = new WMS_TASK { F_addTime = DateTime.Now, F_addUserNo = LoginUser.UserNo, F_trayNo = tray.F_trayNo, F_priority = (int)EPriority.NotUrgent, F_taskStatus = (int)ETaskStatus.NotIssued, F_taskType = (int)ETaskComType.OutStock, F_orderType = (int)ETaskOrderType.StockOutOrderTypeProduct, F_posidFrom = location.F_no, //F_boxNo = item.F_boxNo, F_isBonded = location.F_isBonded, F_orderNo = orderRequest.F_no, F_posidcur = location.F_no, //F_posidNext = location.F_no, F_EquipmentType = (int)EEquipmentType.RGV }; //分配出料口 var curMatInv = ctx.Queryable().Where(c => c.F_trayNo == tray.F_trayNo); if (tray.qty == curMatInv.Sum(s => s.F_quantity)) { //当前托盘数量等于指定数量则整盘出 task.F_posidTo = new AppCoreBLL().GetFreePointInfoByType((int)EPointType.ZPKCK).F_no; task.F_posidNext = task.F_posidTo; } else { if(string.IsNullOrWhiteSpace(orderRequest.PickPort)) throw SysExCore.ThrowFailException($"该托不满足整盘出请选择拣选口!"); var kvPort = dicPort.OrderBy(o => o.Value).FirstOrDefault(); dicPort[kvPort.Key] += 1; task.F_posidTo = kvPort.Key; task.F_pickPort = kvPort.Key; task.F_posidNext = kvPort.Key; } ctx.Insertable(task).ExecuteCommand(); //锁定货位 ctx.Updateable().SetColumns(it => new BASE_LOCATION { F_editTime = DateTime.Now, F_editUserNo = LoginUser.UserNo, F_status = (int)EWareCellState.Out, }).Where(w => w.F_no == location.F_no).ExecuteCommand(); }); ctx.Updateable().SetColumns(it => new BILL_STOCKOUT { F_editTime = DateTime.Now, F_editUserNo = LoginUser.UserNo, F_orderStatus = (int)EOrderState.Executing, }).Where(w => w.F_no == orderRequest.F_no).ExecuteCommand(); ctx.CommitTran(); } catch (Exception e) { ctx.RollbackTran(); throw e; } } } /// /// 保存原料出库单 /// /// public void SoMatSave(StockOutRequest orderRequest, List sod_det, LoginUserInfo loginUserInfo) { //同步出库单明细 using (var ctx = SysDbCore.GetDbCtx()) { try { if (!sod_det.Any()) throw SysExCore.ThrowFailException($"明细不能为空!"); if (ctx.Queryable().Any(c => c.F_relatedOrderNo == orderRequest.F_no)) throw SysExCore.ThrowFailException($"工单{orderRequest.F_no}已生成出库任务!"); if (sod_det.Any(c => string.IsNullOrWhiteSpace(c.FromLoc))) throw SysExCore.ThrowFailException($"明细托盘号不能为空!"); ctx.BeginTran(); var bILL_STOCKOUT = new BILL_STOCKOUT { F_addTime = DateTime.Now, F_addUserNo = loginUserInfo.UserNo, F_no = SerialNumberProvider.Instance.OrderNumber("wms", "CK"), F_orderStatus = (int)EOrderState.New, F_orderType = (int)EStockOutOrderType.StockOutOrderTypeMaterial, F_relatedOrderNo = sod_det.FirstOrDefault().IssNbr, F_totalOrderLines = sod_det.Count, F_warehouseNo = SysSetCore.GetSysSet().DefaultWarehouseNo }; ctx.Insertable(bILL_STOCKOUT).ExecuteCommand(); //出库明细 var matGrp = sod_det.GroupBy(g => new { g.FromPart, g.IssNbr }).Select(s => new FX_TranD { IssNbr = s.Key.IssNbr, FromPart = s.Key.FromPart, QtyExp = s.Sum(k => k.QtyExp) }).ToList(); var dicPort = GetPickPort(ctx, orderRequest.PickPort); foreach (var orderLine in matGrp) { var line = new BILL_STOCKOUTLINE { F_addTime = DateTime.Now, //F_actualQty = orderLine.sod_qty_ship, F_planQty = orderLine.QtyExp, F_matNo = orderLine.FromPart, F_matName = CacheFacade.GetMatInfo(orderLine.FromPart, EMatType.Mat)?.F_matName, F_matType = (int)EMatType.Product, F_orderLineNo = matGrp.IndexOf(orderLine) + 1, F_pNo = bILL_STOCKOUT.F_no, F_warehouseNo = bILL_STOCKOUT.F_warehouseNo, F_addUserNo = loginUserInfo.UserNo }; ctx.Insertable(line).ExecuteCommand(); } //出库实际明细 var matInfoGrp = sod_det.GroupBy(g => new { g.FromPart, g.IssNbr, g.FromLoc }).Select(s => new FX_TranD { IssNbr = s.Key.IssNbr, FromPart = s.Key.FromPart, FromLoc = s.Key.FromLoc, QtyExp = s.Sum(k => k.QtyExp) }).ToList(); foreach (var orderLine in matInfoGrp) { var inv = ctx.Queryable().First(f => f.F_trayNo == orderLine.FromLoc && f.F_matNo == orderLine.FromPart); if (inv == null || inv.F_quantity < orderLine.QtyExp) throw SysExCore.ThrowFailException($"托盘{ orderLine.FromLoc}物料{orderLine.FromPart}库存不够!"); var location = ctx.Queryable().First(f => f.F_trayNo == orderLine.FromLoc && f.F_status == (int)EWareCellState.Stored); if (location == null) throw SysExCore.ThrowFailException($"托盘{ orderLine.FromLoc}货位数据异常!"); ctx.Insertable(new BILL_STOCKOUTLINEDETAIL { F_addTime = DateTime.Now, F_addUserNo = loginUserInfo.UserNo, //F_boxNo = item.F_boxNo, F_locationNo = location.F_no, F_matNo = orderLine.FromPart, F_matName = CacheFacade.GetMatInfo(orderLine.FromPart, EMatType.Mat)?.F_matName, F_matType = (int)EMatType.Mat, F_pNo = bILL_STOCKOUT.F_no, F_quantity = orderLine.QtyExp, F_trayNo = orderLine.FromLoc }).ExecuteCommand(); var task = new WMS_TASK { F_addTime = DateTime.Now, F_addUserNo = loginUserInfo.UserNo, F_trayNo = orderLine.FromLoc, F_priority = orderRequest.F_priority, F_taskStatus = (int)ETaskStatus.NotIssued, F_taskType = (int)ETaskComType.OutStock, F_orderType = (int)ETaskOrderType.StockOutOrderTypeMaterial, F_posidFrom = location.F_no, F_isBonded = location.F_isBonded, F_orderNo = bILL_STOCKOUT.F_no, F_posidcur = location.F_no, //F_posidNext = ctx.Queryable().First(c => c.F_type == (int)EPointType.CKXYGDZ).F_no, F_EquipmentType = (int)EEquipmentType.RGV }; //分配出料口 var curMatInv = ctx.Queryable().Where(c => c.F_trayNo == orderLine.FromLoc); var matInvQty = curMatInv.Sum(s => s.F_quantity); if (orderLine.QtyExp == matInvQty) { //当前托盘数量等于指定数量则整盘出 task.F_posidNext = new AppCoreBLL().GetFreePointInfoByType((int)EPointType.ZPKCK).F_no; task.F_posidTo = new AppCoreBLL().GetFreePointInfoByType((int)EPointType.CPAGV).F_no; } else { var kvPort = dicPort.OrderBy(o => o.Value).FirstOrDefault(); dicPort[kvPort.Key] += 1; task.F_posidTo = kvPort.Key; task.F_posidNext = kvPort.Key; task.F_pickPort = kvPort.Key; } ctx.Insertable(task).ExecuteCommand(); //锁定出库库存 ctx.Updateable().SetColumns(it => new BASE_LOCATION() { F_addTime = DateTime.Now, F_editUserNo = loginUserInfo.UserNo, F_status = (int)EWareCellState.Out, }).Where(w => w.F_no == location.F_no).ExecuteCommand(); } sod_det.ForEach(det => { det.AddTime = DateTime.Now; det.AddUserNo = loginUserInfo.UserNo; }); ctx.Insertable(sod_det).ExecuteCommand(); ctx.CommitTran(); } catch (Exception ex) { ctx.RollbackTran(); throw ex; } } } /// /// 系统推荐出库 /// /// /// /// public void SystemAssignCreate(string no, LoginUserInfo LoginUser) { using (var ctx = SysDbCore.GetDbCtx()) { try { //根据出库单获取明细》根据物料查询库存》推荐库存(先进先出)》生成任务》更新货位状态、新增出库明细 //var matInfo = ctx.Queryable().Where(c => c.F_pNo == no && c.F_matNo == lineDetailsRequest.FirstOrDefault().F_matNo).First(); //if (matInfo.F_planQty != lineDetailsRequest.Sum(s => s.F_quantity)) // SysExCore.ThrowFailException("不允许部分指定!"); //ctx.BeginTran(); //ctx.Insertable(lineDetailsRequest); //ctx.Updateable().SetColumns(it => new BILL_STOCKOUTLINE //{ // F_actualQty = lineDetailsRequest.Sum(s => s.F_quantity), // F_editUserNo = LoginUser.UserNo, // F_editTime = DateTime.Now, //}).Where(w => w.F_rowNo == matInfo.F_rowNo).ExecuteCommand(); ////var dicPort = new Dictionary(orderRequest.DicPickPort); //foreach (var item in lineDetailsRequest) //{ // var location = ctx.Queryable().First(f => f.F_trayNo == item.F_trayNo && f.F_status == (int)EWareCellState.Stored); // if (location == null) // throw SysExCore.ThrowFailException($"托盘{item.F_trayNo}货位数据异常!"); // ctx.Insertable(new BILL_STOCKOUTLINEDETAIL // { // F_addTime = DateTime.Now, // F_addUserNo = LoginUser.UserNo, // F_boxNo = item.F_boxNo, // F_locationNo = location.F_no, // F_matNo = item.F_matNo, // F_matType = item.F_matType, // F_pNo = no, // F_quantity = item.F_AssignQty, // F_trayNo = item.F_trayNo // }).ExecuteCommand(); // ctx.Updateable().SetColumns(it => new BILL_STOCKOUT // { // F_editTime = DateTime.Now, // F_editUserNo = LoginUser.UserNo, // F_orderStatus = (int)EOrderState.NotExecute, // }).Where(w => w.F_no == orderRequest.F_pNo).ExecuteCommand(); //} } catch (Exception e) { ctx.RollbackTran(); throw e; } } } /// /// 获取拣选口 /// /// /// /// public Dictionary GetPickPort(SqlSugarClient ctx, string pickPortArrayStr) { string[] pickPortArray = pickPortArrayStr.Split(','); var pickPortDic = pickPortArrayStr.Split(',').ToDictionary(d => d, d => 0); var cachePortLst = ctx.Queryable().Where(p => SqlFunc.ContainsArray(pickPortArray, p.F_no)).ToList(); foreach (var item in cachePortLst) { if (!string.IsNullOrWhiteSpace(item.F_cachePoint)) pickPortDic.Add(item.F_cachePoint, 0); } return pickPortDic; } } }