using System; using System.Collections.Generic; using SqlSugar; using System.Linq; using System.Linq.Expressions; using Model.InterFaceModel; using Model.ModelDto; using SqlSugar.Extensions; using WMS.Entity.BllSoEntity; using WMS.Entity.Context; using WMS.Entity.DataEntity; using WMS.Entity.SysEntity; using WMS.IBLL.IPdaServer; using Newtonsoft.Json; using WMS.BLL.Logic; using WMS.BLL.LogServer; using WMS.DAL; using WMS.Entity.LogEntity; using Model.ModelDto.BllSoDto; using Utility.Tools; namespace WMS.BLL.BllPdaServer { public class PdaSoServer : IPdaSoServer { private static readonly SqlSugarScope Db = DataContext.Db; //验证托盘是否存在并是否可出库 public string IsEnableOkPalletNo(string palletNo) { try { string sqlMsg = ""; var models = Db.Queryable().Where(m => m.IsDel == "0" && m.PalletNo == palletNo).ToList(); if (models.Count > 1) { sqlMsg = "-1:存在重复托盘号,请检查!"; return sqlMsg; } if (models.Count > 0) { if (models[0].Status == "0") { sqlMsg = "-1:托盘号状态为未使用!"; } } else { sqlMsg = "-1:托盘号不存在!"; } return sqlMsg; } catch (Exception ex) { throw new Exception(ex.Message); } } //获取托盘中含有的执行中的单据 public List GetRunSoNoticeList(string palletNo) { try { if (string.IsNullOrWhiteSpace(palletNo))//判断托盘是否为空 { throw new Exception("托盘码为空,请输入托盘码"); } //获取状态为待拣货或者部分拣货的出库单 var allotList = Db.Queryable().Where(m => m.IsDel == "0" && (m.Status == "2" || m.Status == "3") && m.PalletNo == palletNo).Select(m => m.SONo).Distinct().Where(m => !string.IsNullOrWhiteSpace(m)).ToList(); return allotList; } catch (Exception ex) { throw new Exception(ex.Message); } } //获取出库托盘上的物料批次(根据托盘码) public List GetSoSkuLotNoListByPallet(string palletNo, string soNo) { try { if (string.IsNullOrWhiteSpace(palletNo))//判断托盘是否为空 { throw new Exception("托盘码为空,请输入托盘码"); } //获取状态为待拣货或者部分拣货的出库单 var allotList = Db.Queryable().Where(m => m.IsDel == "0" && (m.Status == "2" || m.Status == "3") && m.PalletNo == palletNo); if (!string.IsNullOrWhiteSpace(soNo)) { allotList = allotList.Where(m => m.SONo == soNo); } var list = allotList.GroupBy(m => new { m.SODetailNo, m.SkuNo, m.SkuName, m.LotNo }).Select(m => new DetailIdSkuLotNo() { SoDetailId = m.SODetailNo, SkuNo = m.SkuNo, SkuName = m.SkuName, LotNo = m.LotNo, }).ToList(); return list; } catch (Exception ex) { throw new Exception(ex.Message); } } //获取出库口、规格、待拣及已拣数量(根据出库单明细ID、托盘号) public OutPdaInfo GetOutlets(string soDetailId, string palletNo) { try { var allotInfo = Db.Queryable().Where(m => m.IsDel == "0" && m.SODetailNo == int.Parse(soDetailId) && m.PalletNo == palletNo && (m.Status == "2" || m.Status == "3")).ToList(); if (allotInfo.Count > 1) { throw new Exception($"{palletNo}托盘上存在多条相同的分配信息,请核实"); } if (allotInfo.Count <= 0) { throw new Exception($"{palletNo}托盘上货物已拣货完毕或不存在拣货信息,请核查!"); } var data = allotInfo.First(); var data2 = new OutPdaInfo() { OutModel = data.OutMode, Standard = data.Standard, PickQty = data.Qty, PickedQty = data.CompleteQty, BoxexQty = data.BoxexQty }; return data2; } catch (Exception e) { throw new Exception(e.Message); } } //获取出库单的计划数量和完成 public OutPdaInfo GetPlanAndFinishQty(string soDetailId) { try { var detail = Db.Queryable().First(m => m.Id == int.Parse(soDetailId) && m.IsDel == "0"); if (detail == null) { throw new Exception("未查询到出库单的明细"); } var data = new OutPdaInfo() { PlanQty = detail.Qty, FinishQty = detail.CompleteQty }; return data; } catch (Exception e) { throw new Exception(e.Message); } } //获取箱码信息(根据箱码在库存箱码明细中查询) public BoxInfo GetBoxInfo(string boxNo, string boxNo2, string boxNo3) { try { Expression> item = Expressionable.Create() .AndIF(!string.IsNullOrWhiteSpace(boxNo), it => it.BoxNo == boxNo) .AndIF(!string.IsNullOrWhiteSpace(boxNo2), it => it.BoxNo2 == boxNo2) .AndIF(!string.IsNullOrWhiteSpace(boxNo3), it => it.BoxNo3 == boxNo3) .And(m => m.IsDel == "0") .ToExpression();//注意 这一句 不能少 var info = Db.Queryable().Where(item).GroupBy(m => m.BoxNo).Select(m => SqlFunc.AggregateSum(m.Qty)).ToList(); if (info.Count == 0) { throw new Exception("未在库存中查询到箱码信息"); } var data = new BoxInfo() { Qty = info[0] }; return data; } catch (Exception e) { throw new Exception(e.Message); } } //获取托盘拣货明细的信息 public List GetComDetailByPalletNo(string palletNo, string soDetailId) { try { var allotInfo = Db.Queryable().Where(m => m.IsDel == "0" && m.SODetailNo == int.Parse(soDetailId) && m.PalletNo == palletNo && (m.Status == "2" || m.Status == "3")).ToList(); if (allotInfo.Count > 1) { throw new Exception($"{palletNo}托盘上存在多条相同的分配信息,请核实"); } if (allotInfo.Count <= 0) { throw new Exception($"{palletNo}托盘上货物已拣货完毕或不存在拣货信息,请核查!"); } var data = allotInfo.First(); var list = new List(); var t = new BoxInfo() { SkuNo = data.SkuNo, SkuName = data.SkuName, LotNo = data.LotNo, PickedQty = data.CompleteQty, }; list.Add(t); //var info = Db.Queryable().Where(m => m.IsDel == "0" && m.ExportAllotId == data.Id).ToList(); //var list = new List(); //foreach (var item in info) //{ // var t = new BoxInfo() // { // BoxNo = item.BoxNo, // SkuNo = item.SkuNo, // SkuName = item.SkuName, // LotNo = item.LotNo, // PickedQty = item.CompleteQty, // }; // list.Add(t); //} return list; } catch (Exception e) { throw new Exception(e.Message); } } //出库pda拣货 public void SoSetPick(string soNo, string soDetailId, string palletNo, int pickQty, int userId) { Db.BeginTran(); try { #region 判断 if (string.IsNullOrWhiteSpace(soNo)) { throw new Exception("出库单据不能为空"); } if (string.IsNullOrWhiteSpace(soDetailId)) { throw new Exception("出库物料-批次不能为空"); } if (string.IsNullOrWhiteSpace(palletNo)) { throw new Exception("托盘码不能为空"); } //if (string.IsNullOrWhiteSpace(boxNo)) //{ // throw new Exception("箱码不能为空"); //} //出库单 var notice = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == soNo); if (notice == null) { throw new Exception("未查询到该出库单的信息"); } if (notice.Status != "3") { throw new Exception("出库单的状态不是正在执行,不能拣货"); } //出库单明细 var noticeDetail = Db.Queryable() .First(m => m.IsDel == "0" && m.Id == int.Parse(soDetailId)); if (noticeDetail == null) { throw new Exception("未查询到该出库单明细的信息"); } //出库分配信息 var allot = Db.Queryable().First(m => m.IsDel == "0" && (m.Status == "2" || m.Status == "3") && m.SONo == soNo && m.SODetailNo == int.Parse(soDetailId) && m.PalletNo == palletNo); if (allot == null) { throw new Exception("未查询到该托盘的分配信息"); } //剩余拣货数量(待拣减去已拣) var needQty = allot.Qty - allot.CompleteQty; if (needQty <= 0) { throw new Exception("当前托盘拣货数量已完成,请勿重复拣货"); } if (pickQty > needQty) { throw new Exception("拣货数量大于当前剩余的拣货数量,请核实!"); } //库存 var stock = Db.Queryable().First(m => m.IsDel == "0" && m.SkuNo == noticeDetail.SkuNo && m.LotNo == noticeDetail.LotNo); if (stock == null) { throw new Exception("未查询到该托盘分配的库存信息!"); } //库存明细 var stockDetail = Db.Queryable().First(m => m.IsDel == "0" && m.Id == allot.StockId); if (stockDetail == null) { throw new Exception("未查询到该托盘分配的库存明细信息!"); } //库存箱码 var stockBox = Db.Queryable().Where(m => m.IsDel == "0" && m.StockDetailId == stockDetail.Id).ToList(); var sku = Db.Queryable().First(m => m.IsDel == "0" && m.SkuNo == stock.SkuNo); #endregion #region 箱码判断 //List boxInfos; //if (!string.IsNullOrWhiteSpace(boxNo3)) //是否整箱 //{ // var boxInfo = Db.Queryable().Where(m => m.IsDel == "0" && m.BoxNo3 == boxNo3); // boxInfos = boxInfo.ToList(); // if (boxInfo.Count() == 0) // { // throw new Exception("未查询到该箱码及追溯码的信息"); // } // if (boxInfo.Count() > 1) // { // throw new Exception("该箱码及追溯码的信息大于1,信息错误,请核实!"); // } // if (boxInfo.Any(m => m.PalletNo != palletNo)) // { // throw new Exception("该托盘与箱码没有绑定关系"); // } // var boxQty = boxInfo.First().Qty; // if (boxQty > needQty) // { // throw new Exception("拣货数量不能大于剩余待拣数量"); // } //} //else if(!string.IsNullOrWhiteSpace(boxNo2)) //是否整盒 //{ // var boxInfo = Db.Queryable().Where(m => m.IsDel == "0" && m.BoxNo2 == boxNo2); // boxInfos = boxInfo.ToList(); // if (boxInfo.Count() == 0) // { // throw new Exception("未查询到该箱码及盒码的信息"); // } // if (boxInfo.Any(m => m.PalletNo != palletNo)) // { // throw new Exception("该托盘与箱码没有绑定关系"); // } // var boxQty = boxInfo.GroupBy(m => m.BoxNo2).Select(m => SqlFunc.AggregateSum(m.Qty)).ToList(); // if (boxQty[0] > needQty) // { // throw new Exception("拣货数量不能大于剩余待拣数量"); // } //} //else //{ // if (string.IsNullOrWhiteSpace(boxNo)) //判断支码是否为空 // { // throw new Exception("追溯码不能为空"); // } // var boxInfo = Db.Queryable().Where(m => m.IsDel == "0" && m.BoxNo == boxNo); // boxInfos = boxInfo.ToList(); // if (boxInfo.Count() == 0) // { // throw new Exception("未查询到该箱码的信息"); // } // if (boxInfo.Any(m => m.PalletNo != palletNo)) // { // throw new Exception("该托盘与箱码没有绑定关系"); // } // var boxQty = boxInfo.GroupBy(m => m.BoxNo).Select(m => SqlFunc.AggregateSum(m.Qty)).ToList(); // if (boxQty[0] > needQty) // { // throw new Exception("拣货数量不能大于箱内剩余待拣数量"); // } //} #endregion var comDetail = Db.Queryable().First(m => m.IsDel == "0" && m.PalletNo == palletNo && m.ExportAllotId == allot.Id); var comList = new List(); foreach (var item in stockBox) { if (comDetail != null) { comDetail.CompleteQty += pickQty; Db.Updateable(comDetail).ExecuteCommand(); continue; } else { //添加拣货明细 var completeDetail = new BllCompleteDetail() { SONo = soNo, SODetailNo = int.Parse(soDetailId), ExportAllotId = allot.Id, StockId = allot.StockId, BoxNo = item.BoxNo, BoxNo2 = item.BoxNo2, BoxNo3 = item.BoxNo3, LotNo = allot.LotNo, LotText = allot.LotText, SupplierLot = allot.SupplierLot, SkuNo = allot.SkuNo, SkuName = allot.SkuName, Standard = allot.Standard, PalletNo = palletNo, CompleteQty = pickQty, CreateUser = userId }; comList.Add(completeDetail); } if (notice.Type == "4")//判断是否是质检取样拣货 { continue; } item.Qty -= pickQty; if (item.Qty == 0) { //删除库存箱码明细 Db.Deleteable(item).ExecuteCommand(); } else { Db.Updateable(item).ExecuteCommand(); } } if (comList.Count > 0) { Db.Insertable(comList).ExecuteCommand(); } //修改出库分配信息 allot.CompleteQty += pickQty; allot.Status = allot.Qty == allot.CompleteQty ? "5" : "3"; Db.Updateable(allot).ExecuteCommand(); //删除或修改库存 if (notice.Type != "4") { stock.Qty -= pickQty; } stock.LockQty -= pickQty; if (stock.Qty <= 0) { Db.Deleteable(stock).ExecuteCommand(); } else { Db.Updateable(stock).ExecuteCommand(); } //删除或修改库存明细 if (notice.Type != "4") { stockDetail.Qty -= pickQty; } stockDetail.LockQty -= pickQty; if (stockDetail.LockQty > 0 && stockDetail.LockQty < stockDetail.Qty) { stockDetail.Status = "1"; } else if (stockDetail.LockQty == 0) { stockDetail.Status = "0"; } if (stockDetail.Qty <= 0) { Db.Deleteable(stockDetail).ExecuteCommand(); } else { Db.Updateable(stockDetail).ExecuteCommand(); } var num2 = Db.Queryable().Count(m => m.IsDel == "0" && m.PalletNo == palletNo); if (num2 <= 0) { //改变托盘状态 var pallet = Db.Queryable().First(m => m.PalletNo == palletNo && m.IsDel == "0"); if (pallet == null) { throw new Exception("未在托盘表中查询到托盘信息"); } pallet.Status = "0"; Db.Updateable(pallet).ExecuteCommand(); } //修改出库单明细拣货数量 noticeDetail.CompleteQty += pickQty; if (noticeDetail.Qty == noticeDetail.CompleteQty) { noticeDetail.Status = "3"; } Db.Updateable(noticeDetail).ExecuteCommand(); var num = Db.Queryable() .Count(m => m.IsDel == "0" && m.SONo == soNo && m.CompleteQty < m.Qty); if (num <= 0) { notice.Status = "4"; //更改为执行完成 Db.Updateable(notice).ExecuteCommand(); } #region 库存记录 //获取对应物料当天库存信息 string strinfo = $"select top 1 * from DataStockInfo where IsDel = '0' and SkuNo = '{stockDetail.SkuNo}' order by CreateTime desc"; var datainfo = Db.Ado.SqlQuerySingle(strinfo); //datainfo.ArrivalQty += item.Qty;//入库数量 datainfo.ExportQty += pickQty;//出库数量 datainfo.BalanceQty -= pickQty;//结存数量 datainfo.YearBalanceQty -= pickQty;//结存数量(月) datainfo.YearExportQty += pickQty;//出库数量(月) Db.Updateable(datainfo).ExecuteCommand(); #endregion Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } //下发空托出库 public List IssuePlnOutHouse(int num, string outMode) { try { throw new NotImplementedException(); } catch (Exception e) { throw new Exception(e.Message); } } //平库出库完成 public void PlaneExportSuccess(string soNo, string palletNo) { try { } catch (Exception e) { throw new Exception(e.Message); } } #region 申请空托盘 /// /// pda申请空托出库 /// /// 物料号 /// 操作人 /// 下发人 /// 来源PC、否则为空 /// public List PalletLocation(string skuNo, int userId, string url, string origin) { OutCommandDto comDto;//返回wcs的入库命令 try { var outDto1 = new List(); //先出库数据的集合(深度为1的储位) var outDto2 = new List(); //后出库数据的集合(深度为2的储位) var moveDto = new List(); //要移库数据的集合 var com = new Common(); Db.BeginTran(); //先进行分配 因为无出库单 //此物品直接拣货成功 //根据托盘号前往库位查询库存明细表信息 //获取以后根据最大任务号生成任务 //判断储位信息 深度为1 直接出库并下发出库任务 同时库存明细表中 增加分配数量 锁定数量 出库后直接拣货完成 更改库存表状态 //深度为2 先进行移库 再下发出库任务 下发移库任务和出库任务同时下发 移库时 修改库存明细表状态为 移库锁定 锁定数量 库存总表增加锁定数量 分配最近储位 下发移库任务 //新增任务 #region 空托盘出库业务 #region 判断 //获取物料信息 var sku = Db.Queryable().First(m => m.SkuNo == skuNo && m.IsDel == "0"); var roadway = Db.Queryable().Where(a => a.IsDel == "0" && a.WareHouseNo == "W03" && a.Status == "0").Select(a => a.RoadwayNo).ToList(); if (roadway.Count == 0) { throw new Exception("当前巷道已被全部禁用!"); } //先获取库存总表是否存在该空托盘在库中 var dataStock = Db.Queryable().First(m => m.SkuNo == skuNo && m.IsDel == "0" && (m.Qty - m.FrozenQty - m.LockQty - m.FrozenQty) > 0); if (dataStock == null) { //库存中没有该空托盘剁 throw new Exception("库存中没有该空托盘剁!"); } //根据库存总表获取库存明细信息 库存状态为待分配和部分分配 var dataStockDeali = Db.Queryable().Where(m => roadway.Contains(m.RoadwayNo) && m.SkuNo == skuNo && m.IsDel == "0" && (m.Qty - m.FrozenQty - m.LockQty - m.FrozenQty) > 0 && m.Status == "0" || m.Status == "1").OrderBy(m => m.CompleteTime).ToList(); //判断空托盘是否有待分配和部分分配 if (dataStockDeali.Count == 0) { //库内该空托盘没有待分配和部分分配的 throw new Exception("库内该空托盘没有待分配和部分分配的!"); } //判断是否已存在该任务 存在返回 var logTasks = Db.Queryable().First(m => m.IsDel == "0" && m.Type == "1" && m.PalletNo == dataStockDeali[0].PalletNo && (m.Status == "1" || m.Status == "0")); if (logTasks != null) { throw new Exception("已存在正在执行或等待执行的托盘任务!"); } #endregion #region 包装信息 ////包装信息 //var packList = Db.Queryable().First(m => m.PackagNo == sku.PackagNo && m.IsDel == "0"); //if (packList == null) //{ // throw new Exception("未查询到物料包装"); //} //var pNum = 0;//托盘物品数量 //var bNum = 0;//箱物品数量 //if (packList.L5Num.HasValue) //{ // pNum = Convert.ToInt32(packList.L5Num); // bNum = Convert.ToInt32(packList.L4Num); //} //else if (packList.L4Num.HasValue) //{ // pNum = Convert.ToInt32(packList.L4Num); // bNum = Convert.ToInt32(packList.L3Num); //} //else if (packList.L3Num.HasValue) //{ // pNum = Convert.ToInt32(packList.L3Num); // bNum = Convert.ToInt32(packList.L2Num); //} //else if (packList.L2Num.HasValue) //{ // pNum = Convert.ToInt32(packList.L2Num); // bNum = Convert.ToInt32(packList.L1Num); //} //else if (packList.L1Num.HasValue) //{ // pNum = Convert.ToInt32(packList.L1Num); // bNum = Convert.ToInt32(packList.L1Num); //} //if (pNum == 0) //{ // throw new Exception("未查询到物料包装托箱关系信息"); //} #endregion #region 分配 //进行分配空托盘 var assign = new AllotSku(); //取合适库存商品 //Dictionary stockQtyDic = new Dictionary();//托出库物品数 //分配货物 //int qty = assign.AllotPallets(dataStockDeali, (int)dataStockDeali[0].Qty, (int)dataStockDeali[0].Qty, 1, stockQtyDic); //获取库存明细信息 DataStockDetail stockDeali = new DataStockDetail(); foreach (var sc in dataStockDeali) { stockDeali = dataStockDeali.First(it => it.Id == sc.Id); //var s = dataStockDeali.FirstOrDefault(m => m.Id == sc.Id); //添加分配表信息 var allot = new BllExportAllot { SONo = "", WaveNo = "", SODetailNo = 0, StockId = sc.Id, LotNo = "", LotText = "", SupplierLot = "", SkuNo = sc.SkuNo, SkuName = sc.SkuName, Standard = sc.Standard, PalletNo = sc.PalletNo, IsBale = "0", //是否裹包 IsBelt = "0", //是否打带 BoxexQty = sc.Qty, Qty = (int)sc.Qty, CompleteQty = 0, Status = "0", LogisticsId = 0, IsAdvance = "0", OutMode = "",//出库口 CreateUser = 0, CreateTime = DateTime.Now }; Db.Insertable(allot).ExecuteCommand(); dataStock.LockQty += (int)sc.Qty; sc.LockQty += sc.Qty; if (sc.LockQty == sc.Qty) { sc.Status = "2"; } else { sc.Status = "1"; } Db.Updateable(dataStock).ExecuteCommand(); //库存总表锁定数量修改 var sd = Db.Updateable(sc).UpdateColumns(it => new { it.LockQty, it.Status }).ExecuteCommand(); //库存明细总表锁定数量修改 break; } #endregion #region 出库 //所有要出库的出库分配信息(未下发的信息和待拣货的信息) var list = Db.Queryable().Where(a => a.IsDel == "0" && a.SkuNo == stockDeali.SkuNo && a.PalletNo == stockDeali.PalletNo && (a.Status == "0" || (a.Status == "2" && a.CompleteQty == 0))).ToList(); if (list.Count == 0) //判断是否有需要下发的出库流水 { throw new Exception("当前出库单据无需要下发的托盘"); } //要出库的托盘集合 var outLpnList = list.Select(m => m.PalletNo).ToList(); //要出库的明细集合 var outStockDetail = Db.Queryable().Where(m => m.IsDel == "0" && outLpnList.Contains(m.PalletNo)).ToList(); //记录错误信息的集合 var flagList = new List();//1:当前要出库的储位正在移出、2 出库的托盘储位信息错误(在储位表中未查询到)、3储位损坏不能出库、4 要出库的托盘正在入库,5 双深度出库前面储位是入库中或者移入中 //循环分配的信息生成出库任务 foreach (var item in list) { var taskNoStr = ""; var stockDetail = outStockDetail.First(m => m.PalletNo == item.PalletNo); // 储位号 var locateNo = stockDetail.LocatNo; //托盘上物料(用于判断物料是否是桶装类型) var skuinfo = Db.Queryable().First(m => m.SkuNo == item.SkuNo); #region 判断 //判断托盘是否在库内(不在库内) if (string.IsNullOrWhiteSpace(locateNo)) { //判断托盘是否在入库中 var imBl = com.GetImTask(item.PalletNo); if (imBl != null) { flagList.Add(4); continue; } //(状态为待拣货的 1) if (item.Status == "0") { //if (sku.Type == "2" || sku.Type == "3" || sku.Type == "4")//桶装类型手持拣货 //{ //} //如果不在仓库内,当前分配信息直接更新出库完成 item.Status = "2";//状态 //item.OutMode = "1号口";//出库口 Db.Updateable(item).ExecuteCommand(); } continue; } var locate = Db.Queryable().First(m => m.LocatNo == locateNo && m.IsDel == "0");//当前出库的储位信息 if (locate == null) { flagList.Add(2); continue; } //判断储位标志是否为损坏 if (locate.Flag == "2") { flagList.Add(3); continue; } #endregion if (locate.Status == "1") //有物品 { if (locate.Depth == "01") //深度为1 { #region 添加出库任务 var taskNo = new Common().GetMaxNo("TK"); var exTask = new LogTask //出库任务 { TaskNo = taskNo, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = locate.LocatNo,//起始位置 EndLocat = "",//目标位置 PalletNo = item.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = locate.LocatNo + "的出库任务" }; Db.Insertable(exTask).ExecuteCommand(); outDto1.Add(new OutCommandDto() { StartRoadway = locate.RoadwayNo, //起始巷道 PalletNo = item.PalletNo,//托盘号 StartLocat = locate.LocatNo, // 起始位置 EndLocat = "28", // 目标位置 TaskNo = exTask.TaskNo, // 任务号 Type = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1, SkuType = sku.Type, //物料类型 LotNo = item.LotNo, // 批次 IsBale = item.IsBale, //是否裹包 IsBelt = item.IsBelt, //是否打带 Qty = item.Qty, //拣货数量 //FullQty = (int)item.BoxexQty, //托盘数量 PalletType = stockDetail.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘 }); taskNoStr = exTask.TaskNo; #endregion } else if (locate.Depth == "02") //深度为2 { //获取出库深度为2储位前面的储位信息 var slotBefore = com.GetLocateNoDepth1(locate.WareHouseNo, locate.LocatNo); if (slotBefore.Status == "1") //前面的储位有货物、进行移库操作 { //要出库深度为2的储位前面的储位中货物是否要出库 var isout = outStockDetail.Count(m => m.LocatNo == slotBefore.LocatNo); if (isout <= 0) //进行移库 { //去库存表中找到储位对应的托盘码操作 var stockNew = Db.Queryable().First(m => m.LocatNo == slotBefore.LocatNo); if (stockNew == null) { var slotChange = Db.Queryable().First(m => m.LocatNo == slotBefore.LocatNo); slotChange.Status = "0"; Db.Updateable(slotChange).ExecuteCommand(); } else { //获取移库的库位 var newSlot = MoveAddress(slotBefore.LocatNo, slotBefore.RoadwayNo, slotBefore.AreaNo); //当前移库库位的储位信息 var locatey = Db.Queryable().First(m => m.LocatNo == newSlot && m.IsDel == "0"); if (!string.IsNullOrEmpty(newSlot)) { #region 添加出库时发生的移库任务 var exYkTaskNo = new Common().GetMaxNo("TK"); var exYkTask = new LogTask //出库时产生移库任务 { TaskNo = exYkTaskNo, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = stockNew.LocatNo,//起始位置 EndLocat = newSlot,//目标位置 PalletNo = stockNew.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "2",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = stockNew.LocatNo + " ==>> " + newSlot + "的移库任务", }; Db.Insertable(exYkTask).ExecuteCommand(); moveDto.Add(new OutCommandDto() { StartRoadway = slotBefore.RoadwayNo, //起始巷道 PalletNo = stockNew.PalletNo,//托盘号 StartLocat = stockNew.LocatNo, // 起始位置 EndLocat = newSlot, // 目标位置 EndRoadway = locatey.RoadwayNo, // 目标巷道 TaskNo = exYkTask.TaskNo, // 任务号 Type = "2",// 任务类型 (移库) OutMode = "", //目标地址 Order = 1, SkuType = sku.Type, //物料类型 LotNo = stockNew.LotNo, Qty = 0, //拣货数量 //FullQty = (int)stockNew.Qty, //托盘数量 PalletType = stockNew.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘 }); #endregion #region 改变储位装填 var slotChange = Db.Queryable().First(m => m.Id == slotBefore.Id); var slotChange2 = Db.Queryable().First(m => m.LocatNo == newSlot); slotChange.Status = "5"; //改变状态(正在移出) slotChange2.Status = "4"; // 改变状态(正在移入) Db.Updateable(slotChange).ExecuteCommand(); Db.Updateable(slotChange2).ExecuteCommand(); #endregion } else { #region 添加出库任务 var exYkTaskNo1 = new Common().GetMaxNo("TK"); var exYkTask1 = new LogTask //出库移库没有库位了进行出库任务 { TaskNo = exYkTaskNo1, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = stockNew.LocatNo,//起始位置 EndLocat = "",//目标位置 PalletNo = stockNew.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = locate.LocatNo + "的出库任务" }; Db.Insertable(exYkTask1).ExecuteCommand(); outDto1.Add(new OutCommandDto() { StartRoadway = slotBefore.RoadwayNo, //起始巷道 PalletNo = stockNew.PalletNo,//托盘号 StartLocat = stockNew.LocatNo, // 起始位置 EndLocat = "28", // 目标位置 TaskNo = exYkTask1.TaskNo, // 任务号 Type = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1, SkuType = sku.Type, //物料类型 LotNo = "", // 批次 IsBale = "0", //是否裹包 IsBelt = "0", //是否打带 Qty = 0, //拣货数量 //FullQty = (int)stockNew.Qty, //托盘数量 PalletType = stockNew.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘 }); #endregion #region MyRegion var slotChange = Db.Queryable().First(m => m.Id == slotBefore.Id); slotChange.Status = "3"; //改变状态(正在出库) Db.Updateable(slotChange).ExecuteCommand(); #endregion } } } } else if (slotBefore.Status == "2" || slotBefore.Status == "4") //前面储位状态是入库中或者移入中 { flagList.Add(5); continue; } #region 添加出库任务 var taskNo1 = new Common().GetMaxNo("TK"); var exTask1 = new LogTask //出库任务 { TaskNo = taskNo1, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = locate.LocatNo,//起始位置 EndLocat = "",//目标位置 PalletNo = item.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = locate.LocatNo + "的出库任务" }; Db.Insertable(exTask1).ExecuteCommand(); outDto2.Add(new OutCommandDto() { StartRoadway = locate.RoadwayNo, //起始巷道 PalletNo = item.PalletNo,//托盘号 StartLocat = locate.LocatNo, // 起始位置 EndLocat = "28", // 目标位置 TaskNo = exTask1.TaskNo, // 任务号 Type = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1, SkuType = sku.Type, //物料类型 IsBale = item.IsBale, //是否裹包 IsBelt = item.IsBelt, //是否打带 Qty = item.Qty, //拣货数量 //FullQty = (int)item.BoxexQty, //托盘数量 PalletType = stockDetail.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘 }); taskNoStr = exTask1.TaskNo; #endregion } #region 改变数据 if (item.Status == "0")//判断托盘是否下发过 { var noticeDetail = Db.Queryable().First(m => m.IsDel == "0" && m.Id == item.SODetailNo); if (noticeDetail != null) //更新出库单据的下发数量 { noticeDetail.FactQty += item.Qty; Db.Updateable(noticeDetail).ExecuteCommand(); } } item.TaskNo = taskNoStr; // 出库分配信息中更新任务号 item.Status = "1"; // 出库分配信息状态改为正在执行 Db.Updateable(item).ExecuteCommand(); locate.Status = "3"; //要出库的储位改变状态 正在出库 Db.Updateable(locate).ExecuteCommand(); #endregion flagList.Add(0); } else if (locate.Status == "3") //出库中 { if (sku.Type == "2" || sku.Type == "3" || sku.Type == "4") { continue; } #region 改变数据 //判断是否是已经出过库又回库(状态为待拣货的 1) if (item.Status == "0") { var noticeDetail = Db.Queryable().First(m => m.IsDel == "0" && m.Id == item.SODetailNo); if (noticeDetail != null) //更新出库单据的下发数量 { noticeDetail.FactQty += item.Qty; Db.Updateable(noticeDetail).ExecuteCommand(); } } var taskNo = Db.Queryable().First(m => m.OrderType == "1" && m.TaskNo != item.TaskNo && m.Status == "1" && m.PalletNo == item.PalletNo); item.TaskNo = taskNo.TaskNo; item.Status = "1"; // 出库分配信息状态改为正在执行 Db.Updateable(item).ExecuteCommand(); #endregion } else if (locate.Status == "5") //移出中 { flagList.Add(1); } } //先移库后出库 outDto1.AddRange(moveDto); outDto1.AddRange(outDto2); //var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss") //var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss") //// 正式运行程序放开 //var list2 = outDto1.Select(m => m.TaskNo).ToList(); //var jsonData = JsonConvert.SerializeObject(outDto1); ////更改任务的发送返回时间// //new TaskServer().EditTaskIssueOk(list2, time1, time2); if (outDto1.Count > 0) { // 正式运行程序放开 var list2 = outDto1.Select(m => m.TaskNo).ToList(); var jsonData = JsonConvert.SerializeObject(outDto1); string response = ""; try { var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss") response = HttpHelper.DoPost(url, jsonData, "下发给WCS出库命令", "WCS"); var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss") //解析返回数据 var wcsModel = JsonConvert.DeserializeObject(response); if (wcsModel.stateCode == 1) { //更改任务的发送返回时间// new TaskServer().EditTaskIssueOk(list2, time1, time2); //str += "下发成功"; } if (wcsModel.stateCode == -1) { new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.errMsg); throw new Exception(wcsModel.errMsg); } } catch (Exception ex) { throw new Exception(ex.Message); } } #endregion #endregion if (origin == "PC") { //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", skuNo, "出库", $"选择{skuNo}托盘出库", userId); } Db.CommitTran(); return outDto1; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } #region 移库目标库位 /// /// 获取移库目标库位 /// /// 需要移动的库位地址 /// 巷道 /// 区域 /// 目标库位地址 为"" 直接下发两次出库指令 public string MoveAddress(string oldAddress, string roadWay, string area)//01020201 排-列-层-深度 { string nowAddress = ""; // 获取移库目标储位 var row = int.Parse(oldAddress.Substring(0, 2)); var lie = int.Parse(oldAddress.Substring(2, 2)); var ceng = int.Parse(oldAddress.Substring(4, 2)); var sqlString = $@"select LocatNo,[Row],[Column],Layer, (ABS(Row-{row}) + ABS([Column]-{lie}) + ABS(Layer-{ceng})) as distNum from SysStorageLocat where Flag = '0' and Status in ('0','3','5') and Depth = '02' and RoadwayNo = '{roadWay}' and AreaNo = '{area}' order by distNum;"; var addressModels = Db.Ado.SqlQuery(sqlString).ToList(); if (addressModels.Count > 0) // 判断同巷道内排空库位 { var listLocaete = new List(); foreach (var item in addressModels) { // 目标内库位对应的外库位 string addressee = item.LocatNo.Substring(0, 6) + "01"; // 判断目标库位的外库位是否存在货物 (正常情况下正在移入情况不存在,因为移库先移入里面,后移入外面) //SlotStatus 0: 空储位 1:有货 2:正在入库 3:正在出库 4:正在移入 5:正在移出 sqlString = $"select count(*) from SysStorageLocat where LocatNo = '{addressee}' and Status in ('0','3','5') and Flag in ('0','1') ; "; var rowNum = Db.Ado.SqlQuery(sqlString).First(); if (rowNum == 0) { continue; } else { nowAddress = item.LocatNo; break; } } } if (nowAddress == "") { // 判断同巷道外排空库位 sqlString = $@"select LocatNo,[Row],[Column],Layer, (ABS(Row-{row}) + ABS([Column]-{lie}) + ABS(Layer-{ceng})) as distNum from SysStorageLocat where Flag = '0' and Status in ('0','3','5') and Depth = '01' and RoadwayNo = '{roadWay}' and AreaNo = '{area}' order by distNum;"; var adderModeling = Db.Ado.SqlQuery(sqlString).ToList(); if (adderModeling.Count > 0) { nowAddress = adderModeling[0].LocatNo; } else { // 库内不存在空储位 nowAddress = ""; } } return nowAddress; } #endregion #endregion } }