using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using Model.InterFaceModel; using Model.ModelDto.BllSoDto; using Newtonsoft.Json; using SqlSugar; using WMS.BLL.Logic; using WMS.BLL.LogServer; using WMS.DAL; using WMS.Entity.BllSoEntity; using WMS.Entity.Context; using WMS.Entity.DataEntity; using WMS.Entity.LogEntity; using WMS.Entity.SysEntity; using WMS.IBLL.IBllSoServer; namespace WMS.BLL.BllSoServer { public class WaveMageServer:DbHelper,IWaveMageServer { private static readonly SqlSugarScope Db = DataContext.Db; public WaveMageServer():base(Db) { } //获取波次单信息 public List GetWaveMageList(string waveNo, string status, string lotNo, int? logisticsId, int page, int limit, out int count) { try { Expression> item = Expressionable.Create() .AndIF(!string.IsNullOrWhiteSpace(waveNo), it => it.WaveNo.Contains(waveNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(status), it => it.Status == status) .AndIF(logisticsId != null, it => it.LogisticsId == logisticsId) .AndIF(!string.IsNullOrWhiteSpace(lotNo), it => it.LotNo.Contains(lotNo)) .ToExpression();//注意 这一句 不能少 var total = 0; var data = GetAllWhereAsync(item) .LeftJoin((a, b) => a.LogisticsId == b.Id) .LeftJoin((a, b, c) => a.CreateUser == c.Id) .LeftJoin((a, b, c, d) => a.CreateUser == d.Id) .Select((a, b, c, d) => new WaveMageDto() { Id = a.Id, WaveNo = a.WaveNo, Status = a.Status, Origin = a.Origin, CustomerNo = a.CustomerNo, CustomerName = a.CustomerName, LotNo = a.LotNo, LotText = a.LotText, SupplierLot = a.SupplierLot, LogisticsId = a.LogisticsId, LogisticsName = b.CarrierName, Address = a.Address, CreateUserName = c.RealName, UpdateUserName = c.RealName, CreateTime = a.CreateTime, UpdateTime = a.UpdateTime, }) .OrderByDescending(a => a.CreateTime) .ToOffsetPage(page, limit, ref total); count = total; return data; } catch (Exception e) { throw new Exception(e.Message); } } //获取添加波次单的出库单信息 public List GetAddExNoticeInfo(int? logisticsId, string address) { try { Expression> item = Expressionable.Create() .And(it=>it.IsDel =="0") .And(it=>it.Status == "0") .And(it=>it.Type == "0") .And(it=>it.IsWave == "0") .AndIF(logisticsId != null, it => it.LogisticsId == logisticsId) .AndIF(!string.IsNullOrWhiteSpace(address), it => it.Address.Contains(address)) .ToExpression();//注意 这一句 不能少 var notice = Db.Queryable().Where(item) .LeftJoin((a, b) => a.LogisticsId == b.Id) .Select((a, b) => new ExportNoticeDto() { Id = a.Id, SONo = a.SONo, Type = a.Type, Status = a.Status, Origin = a.Origin, CustomerNo = a.CustomerNo, CustomerName = a.CustomerName, LotNo = a.LotNo, LotText = a.LotText, SupplierLot = a.SupplierLot, LogisticsId = a.LogisticsId, LogisticsName = b.CarrierName, Address = a.Address, IsWave = a.IsWave, WaveNo = a.WaveNo, IsDespatch = a.IsDespatch, CreateTime = a.CreateTime, UpdateTime = a.UpdateTime }).ToList(); return notice; } catch (Exception e) { throw new Exception(e.Message); } } //添加波次单据 public void AddWaveMage(List Ids, int userId) { try { var notice = Db.Queryable().Where(m => m.IsDel == "0" && Ids.Contains(m.Id)).ToList(); if (notice.Count < 2) { throw new Exception("合并波次需要至少两条出库单据信息"); } var soList = notice.Select(m => m.SONo).ToList(); var noticeDetail = Db.Queryable().Where(m => m.IsDel == "0" && soList.Contains(m.SONo)).ToList(); var count1 = 0; var list1 = new List(); var count2 = 0; var list2 = new List(); foreach (var item in notice) { if (item.LogisticsId!= null) { if (!list1.Contains((int)item.LogisticsId)) { list1.Add((int)item.LogisticsId); } } else { if (count1<1) { count1 += 1; } } if (!string.IsNullOrWhiteSpace(item.Address)) { if (list2.Count(m => m == item.Address) == 0) { list2.Add(item.Address); } } else { if (count2 < 1) { count2 += 1; } } } if (list1.Count == 0 && list2.Count == 0) { throw new Exception("承运商与收货地址不能都为空,请核实"); } if ( list1.Count + count1>1 || list2.Count+count2>1) { throw new Exception("承运商或收货地址应一致,请核实"); } Db.BeginTran(); var waveNo = new Common().GetMaxNo("WSO"); var wave = new BllWaveMage() { WaveNo = waveNo, Status = "0", Origin = "WMS", CustomerNo = "", CustomerName = "", LotNo = "", LotText = "", SupplierLot = "", Address = list2.Count>0?list2.First():"", CreateUser = userId }; if (list1.Count > 0) { wave.LogisticsId = list1.First(); } Db.Insertable(wave).ExecuteCommand(); var date = DateTime.Now; foreach (var demo in notice) { if (demo.Type != "0")//成品出库 { throw new Exception("合并波次单的出库单类型应为成品出库"); } if (demo.Status != "0") { throw new Exception("合并波次单的出库单状态应为等待执行"); } if (demo.IsWave == "1") { throw new Exception("合并波次单含有已生成波次的出库单单"); } demo.WaveNo = waveNo; demo.IsWave = "1"; demo.UpdateTime = date; demo.UpdateUser = userId; } foreach (var demo in noticeDetail) { if (demo.IsWave == "1") { throw new Exception("合并波次单含有已生成波次的出库单明细"); } if (demo.Status != "0") { throw new Exception("合并波次单的出库单明细状态应为等待执行"); } demo.WaveNo = waveNo; demo.IsWave = "1"; demo.UpdateTime = date; demo.UpdateUser = userId; } Db.Updateable(notice).ExecuteCommand(); Db.Updateable(noticeDetail).ExecuteCommand(); Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } //删除波次出库单 public bool DelWaveExportNotice(int id, int userId) { try { Db.BeginTran(); var wave = Db.Queryable().First(m => m.IsDel == "0" && m.Id == id); if (wave == null) { throw new Exception("未查询到波次单信息"); } if (wave.Status != "0") { throw new Exception("该波次单据状态不是等待执行,请核实"); } var notice = Db.Queryable().Where(m => m.IsDel == "0" && m.WaveNo == wave.WaveNo).ToList(); if (notice.Count == 0) { throw new Exception("未查询到该波次单下的出库单信息!!!"); } if (notice.Count(m=>m.Status!="0") > 0) { throw new Exception("该波次单下的出库单状态有不是等待执行的!!!"); } var noticeDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.WaveNo == wave.WaveNo).ToList(); if (noticeDetail.Count == 0) { throw new Exception("未查询到该波次单下的出库单信息!!!"); } if (noticeDetail.Count(m => m.Status != "0") > 0) { throw new Exception("该波次单下的出库单明细状态有不是等待执行的!!!"); } var date = DateTime.Now; foreach (var item in notice) { item.IsWave = "0"; item.WaveNo = ""; item.UpdateTime = date; item.UpdateUser = userId; } foreach (var item in noticeDetail) { item.IsWave = "0"; item.WaveNo = ""; item.UpdateTime = date; item.UpdateUser = userId; } var a = Db.Updateable(notice).ExecuteCommand(); var b = Db.Updateable(noticeDetail).ExecuteCommand(); wave.IsDel = "1"; wave.UpdateTime = date; wave.UpdateUser = userId; var c = Db.Updateable(wave).ExecuteCommand(); if (a>0 && b>0 && c>0) { Db.CommitTran(); return true; } throw new Exception("更改错误,请核实"); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } //波次自动分配 public bool WaveAutoAllot(string waveNo, int userId) { try { #region 判断条件(出库单、出库单明细) //波次单 var wave = Db.Queryable().First(m => m.IsDel == "0" && m.WaveNo == waveNo); //出库单 var noticeList = Db.Queryable().Where(m => m.IsDel == "0" && m.WaveNo == waveNo).ToList(); var soList = noticeList.Select(m => m.SONo).ToList(); if (noticeList.Count == 0) { throw new Exception("未查询到出库单据信息"); } if (noticeList.Count(m=> m.Status != "0" && m.Status != "1") > 0) { throw new Exception("参数异常,请检查状态是否为等待执行或部分分配;"); } //出库单明细 var detailList2 = Db.Queryable().Where(m => m.IsDel == "0" && soList.Contains(m.SONo) && m.WaveNo == waveNo && (m.AllotQty - m.Qty) <= 0).ToList(); if (!detailList2.Any()) { throw new Exception("未查询到符合分配条件的出库单据明细信息"); } #endregion //包装信息 var packageNos = detailList2.Select(d => d.PackagNo).ToList(); var packList = Db.Queryable().Where(m => packageNos.Contains(m.PackagNo)).ToList(); var assign = new AllotSku(); Db.BeginTran(); foreach (var notice in noticeList) { var detailList = detailList2.Where(m => m.SONo == notice.SONo).ToList(); var exAllotList = new List(); foreach (var detail in detailList) { if (detail.AllotQty >= detail.Qty) { continue; } //还需要分配的数量 var needQty = detail.Qty - detail.AllotQty; //库存明细 Status 0:待分配 1:部分分配 2:已分配 var stockDetail = Db.Queryable().Where(m => m.SkuNo == detail.SkuNo && (m.Qty - m.FrozenQty - m.LockQty + m.InspectQty) > 0 && (m.Status == "0" || m.Status == "1") && m.IsDel == "0").ToList(); //判断单号是否指定批次 if (!string.IsNullOrWhiteSpace(detail.LotNo)) { if (detail.LotNo.Contains(";")) { var lotNoList = detail.LotNo.Split(";"); var lotNoList2 = new List(); foreach (var lotNoItem in lotNoList) { lotNoList2.Add(lotNoItem); } stockDetail = stockDetail.Where(m => m.SkuNo == detail.SkuNo && lotNoList2.Contains(m.LotNo) && m.IsDel == "0").ToList(); } else { stockDetail = stockDetail.Where(m => m.SkuNo == detail.SkuNo && m.LotNo == detail.LotNo && m.IsDel == "0").ToList(); } } else { stockDetail = stockDetail.Where(m => m.SkuNo == detail.SkuNo && m.IsDel == "0" && string.IsNullOrWhiteSpace(m.LotNo)).ToList(); // } if (stockDetail.Count < 1) { throw new Exception("库存不足,无可出库库存"); } stockDetail = stockDetail.Where(m => m.InspectStatus == "1").ToList(); //0:成品出库、1:领料出库、2:抽检出库、3:物料取样出库、4:不合格品出库、5:中间品出库、6:代储出库、7:其他出库、8:寄存出库 //if (notice.Type == "0" || notice.Type == "1")//成品 //{ // stockDetail = stockDetail.Where(m => m.InspectStatus == "1").ToList(); //} //else if (notice.Type == "3")//取样出库 //{ // stockDetail = stockDetail.Where(m => m.InspectStatus == "0").ToList(); //} //else if (notice.Type == "5" || notice.Type == "6" || notice.Type == "7" || notice.Type == "8") //{ // stockDetail = stockDetail.Where(m => m.InspectStatus == "0" || m.InspectStatus == "1").ToList(); //} //else if (notice.Type == "4")//不合格出库 //{ // stockDetail = stockDetail.Where(m => m.InspectStatus == "2").ToList(); //} #region 包装信息 var pack = packList.FirstOrDefault(p => p.PackagNo == detail.PackagNo); var pNum = 0;//托盘物品数量 var bNum = 0;//箱物品数量 if (pack != null) { //throw new Exception("未查询到物料包装"); if (pack.L5Num.HasValue) { pNum = Convert.ToInt32(pack.L5Num); bNum = Convert.ToInt32(pack.L4Num); } else if (pack.L4Num.HasValue) { pNum = Convert.ToInt32(pack.L4Num); bNum = Convert.ToInt32(pack.L3Num); } else if (pack.L3Num.HasValue) { pNum = Convert.ToInt32(pack.L3Num); bNum = Convert.ToInt32(pack.L2Num); } else if (pack.L2Num.HasValue) { pNum = Convert.ToInt32(pack.L2Num); bNum = Convert.ToInt32(pack.L1Num); } else if (pack.L1Num.HasValue) { pNum = Convert.ToInt32(pack.L1Num); bNum = Convert.ToInt32(pack.L1Num); } } //if (pNum == 0) //{ // throw new Exception("未查询到物料包装托箱关系信息"); //} #endregion //取合适库存商品 Dictionary stockQtyDic = new Dictionary();//托出库物品数 Dictionary zxQtyDic = new Dictionary();//托出整箱数 //分配货物 //assign.AllocatePallets(stocks, pNum, bNum, needQty, stockQtyDic, zxQtyDic); var qty = assign.AllotPallets(stockDetail, decimal.Parse(needQty.ToString()), pNum, bNum, stockQtyDic); foreach (var sc in stockQtyDic) { var s = stockDetail.FirstOrDefault(m => m.Id == sc.Key); //添加分配表信息 var allot = new BllExportAllot { SONo = notice.SONo, WaveNo = waveNo, SODetailNo = detail.Id, StockId = sc.Key, LotNo = s.LotNo, LotText = s.LotText, SupplierLot = s.SupplierLot, SkuNo = s.SkuNo, SkuName = s.SkuName, Standard = s.Standard, PalletNo = s.PalletNo, IsBale = detail.IsBale == "0" ? "0" : s.IsBale == "1" ? "0" : "1", //是否裹包 IsBelt = detail.IsBelt == "0" ? "0" : s.IsBelt == "1" ? "0" : "1", //是否打带 Qty = sc.Value, CompleteQty = 0, //BoxexQty = s.Qty, //箱内数量 Status = "0", LogisticsId = notice.LogisticsId, IsAdvance = "0", OutMode = "",//出库口 CreateUser = userId, CreateTime = DateTime.Now }; exAllotList.Add(allot); s.LockQty += stockQtyDic[s.Id]; if (s.LockQty == s.Qty) { s.Status = "2"; } else { s.Status = "1"; } var sd = Db.Updateable(s).UpdateColumns(it => new { it.LockQty, it.Status }).ExecuteCommand(); //if (notice.Type == "1" || notice.Type == "5" || notice.Type == "6" || notice.Type == "7" || notice.Type == "8")//1:领料出库、 //{ // if (string.IsNullOrWhiteSpace(detail.LotNo)) // { // detail.LotNo = s.LotNo; // } // else // { // if (!detail.LotNo.Contains(s.LotNo)) // { // detail.LotNo += ";" + s.LotNo; // } // } //} } detail.AllotQty += qty; detail.UpdateUser = userId; detail.UpdateTime = DateTime.Now; if (detail.Status == "0") { detail.Status = "1"; } //库存总表 //var stock = Db.Queryable().First(d => d.IsDel == "0" && d.SkuNo == detail.SkuNo && d.LotNo == detail.LotNo); //stock.LockQty += qty; //Db.Updateable(stock).ExecuteCommand(); } var mx = Db.Updateable(detailList).ExecuteCommand(); var fp = Db.Insertable(exAllotList).ExecuteCommand(); //修改分配单据的状态 if (notice.Status == "0" || notice.Status == "1") { var bl = 0; var bl2 = 0; foreach (var item in detailList) { if (item.AllotQty <= 0) { continue; } if (item.AllotQty < item.Qty) { bl = 1; } else { bl2 = 1; } } switch (bl2) { case 1 when bl == 1: notice.Status = "1";//证明部分分配数量全部大于等于出库数量 修改为已分配 break; case 0 when bl == 1: notice.Status = "1";//证明部分分配数量全部大于等于出库数量 修改为已分配 break; case 1 when bl == 0: notice.Status = "2";//证明分配数量全部大于等于出库数量 修改为已分配 break; case 0 when bl == 0: //证明所有分配数量全部小于等于出库数量 不做修改 break; } } notice.UpdateUser = userId; notice.UpdateTime = DateTime.Now; var zd = Db.Updateable(notice).ExecuteCommand(); } //修改波次单 if (noticeList.Count(m=>m.Status != "2") > 0) { throw new Exception("出库单分配数量不足"); } wave.Status = "2"; wave.UpdateTime = DateTime.Now; wave.UpdateUser = userId; var sas = Db.Updateable(wave).ExecuteCommand(); //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "波次管理", waveNo, "分配", $"自动分配了波次单据号为{waveNo}的单据信息", userId); Db.CommitTran(); return true; //if (zd > 0 && mx > 0 && fp > 0 && k) //{ // Db.CommitTran(); // return true; //} //Db.RollbackTran(); //return false; } catch (Exception e) { Db.RollbackTran(); throw new Exception("自动分配失败" + e.Message); } } //波次取消分配 public bool WaveCancelAllot(string waveNo, int userId) { try { var wave = Db.Queryable().First(m => m.IsDel == "0" && m.WaveNo == waveNo); if (wave == null) { throw new Exception("未查询到波次出库单据信息"); } if (wave.Status != "1" && wave.Status!="2") { throw new Exception("请检查状态是否为已分配或部分分配"); } var noticeList = Db.Queryable().Where(m => m.IsDel == "0" && m.WaveNo == waveNo).ToList(); if (noticeList.Count == 0) { throw new Exception("未查询到波次的出库单据信息"); } if (noticeList.Count(m=>m.Status != "1" && m.Status != "2") >0 ) { throw new Exception("请检查状态是否为已分配或部分分配"); } var soList = noticeList.Select(m => m.SONo).ToList(); //该单据的分配信息 Status 0:任务下发 1:待拣货 2:部分拣货 3:待回库 4:已完成 var allotList = Db.Queryable().Where(o => o.IsDel == "0" && soList.Contains(o.SONo)).ToList(); //有已执行的分配数据不能取消 if (allotList.Any(o => o.Status != "0")) { throw new Exception("当前单据的分配信息已有执行中,不能取消分配"); } Db.BeginTran(); //查询分配的明细 var detail2 = Db.Queryable().Where(d => d.WaveNo == waveNo && soList.Contains(d.SONo) && d.AllotQty > 0 && d.IsDel == "0").ToList(); foreach (var notice in noticeList) { var detail = detail2.Where(m => m.SONo == notice.SONo).ToList(); foreach (var d in detail) { var orders = allotList.Where(o => o.SODetailNo == d.Id).ToList(); foreach (var o in orders) { var pq = Db.Queryable().Where(t => t.Id == o.StockId); var pq2 = !string.IsNullOrWhiteSpace(o.LotNo) ? pq.Where(t => t.LotNo == o.LotNo).ToList() : pq.Where(t => string.IsNullOrWhiteSpace(t.LotNo)).ToList(); var pallet = pq2.FirstOrDefault(); if (pallet != null) { pallet.LockQty -= o.Qty; pallet.Status = pallet.LockQty == 0 ? "0" : "1"; //如果锁定数量是0状态变更为待分配 否则为部分分配 Db.Updateable(pallet).ExecuteCommand(); //库存总表 //var stock = Db.Queryable().First(t => t.SkuNo == pallet.SkuNo && t.IsDel == "0"); //stock.LockQty -= o.Qty; //Db.Updateable(stock).ExecuteCommand(); } } Db.Deleteable(orders).ExecuteCommand(); d.AllotQty = 0; d.Status = "0"; d.UpdateUser = userId; d.UpdateTime = DateTime.Now; //if (notice.Type == "1" || notice.Type == "5" || notice.Type == "6" || notice.Type == "7" || notice.Type == "8")//1:领料出库、 //{ // if (d.IsIssueLotNo != "1") // { // d.LotNo = ""; // } //} } notice.Status = "0"; notice.UpdateUser = userId; notice.UpdateTime = DateTime.Now; Db.Updateable(detail).ExecuteCommand(); Db.Updateable(notice).ExecuteCommand(); } if (noticeList.Count(m=>m.Status!="0")>0) { throw new Exception("波次单取消分配有误,出库单含有未取消完成的"); } wave.Status = "0"; wave.UpdateTime = DateTime.Now; wave.UpdateUser = userId; Db.Updateable(wave).ExecuteCommand(); //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "波次管理", waveNo, "取消分配", $"取消分配了波次单据号为{wave.WaveNo}的单据信息", userId); Db.CommitTran(); return true; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } //波次下发出库 public List WaveIssueOutHouse(string waveNo, string unstackingMode, string outMode, string loadingAddre, int userId, string url, out string str) { try { #region 集合 var outDto1 = new List(); //先出库数据的集合(深度为1的储位) var outDto2 = new List(); //后出库数据的集合(深度为2的储位) var moveDto = new List(); //要移库数据的集合 //记录错误信息的集合 var flagList = new List();//1:当前要出库的储位正在移出、2 出库的托盘储位信息错误(在储位表中未查询到)、3储位损坏不能出库、4 要出库的托盘正在入库 #endregion var com = new Common(); //assign.IsHavePyTask(); var wave = Db.Queryable().First(m => m.IsDel == "0" && m.WaveNo == waveNo); if (wave == null) { throw new Exception("未找到当前波次的单信息"); } if (wave.Status !="2") { throw new Exception("当前波次的单状态不是已分配,不能下发出库,请核实"); } var noticeList = Db.Queryable().Where(m => m.WaveNo == waveNo && m.IsDel == "0").ToList(); if (noticeList.Count == 0) { throw new Exception($"未找到{waveNo}波次的出库单信息"); } var soList = noticeList.Select(m => m.SONo).ToList(); //所有要出库的出库分配信息(未下发的信息和待拣货的信息) var list = Db.Queryable().Where(a => a.IsDel == "0" && soList.Contains(a.SONo) && a.WaveNo == waveNo && a.Status == "0").OrderBy(m=>m.SONo).OrderBy(m=>m.SkuNo).ToList(); if (list.Count == 0) //判断是否有需要下发的出库流水 { throw new Exception("当前波次单据无需要下发的托盘"); } #region 集合 //要出库的托盘集合 var outLpnList = list.Select(m => m.PalletNo).ToList(); //要出库的明细集合 var outStockDetail = Db.Queryable().Where(m => m.IsDel == "0" && outLpnList.Contains(m.PalletNo)).ToList(); //物料编码表 var skuList = Db.Queryable().Where(w => w.IsDel == "0"); //包装表 var packagList = Db.Queryable().Where(w => w.IsDel == "0"); Db.BeginTran(); try { List logTaskList = new List();//此次出库任务集合,为应对同托盘不同物料出库 //循环分配的信息生成出库任务 foreach (var item in list) { var taskNoStr = ""; string toLocation = string.Empty;//目标位置 string unstackingMode2 = unstackingMode;//拆垛方式,0:机器人拆垛 1:PDA拆垛 #region 判断是否需要拆箱 string isChai = "0";//是否需要拆箱,0:否 1:是 var skuInfo = skuList.First(w => w.SkuNo == item.SkuNo); if (skuInfo == null) { throw new Exception("物料信息不存在!"); } var packagInfo = packagList.First(w => w.PackagNo == skuInfo.PackagNo); if (packagInfo == null) { throw new Exception("包装信息不存在!"); } if (packagInfo.L2Name == "箱") { if (item.Qty % (decimal)packagInfo.L2Num != 0)//能整除说明不用拆箱,不能整除说明需要拆箱 { isChai = "1"; unstackingMode2 = "1";//需要拆箱需走PDA拆垛 } } if (isChai == "0") { var boxInfo = Db.Queryable().Where(w => w.IsDel == "0" && w.PalletNo == item.PalletNo && w.BitBoxMark == "1").ToList(); if (boxInfo != null)//托盘上有零箱需要拆箱 { isChai = "1"; unstackingMode2 = "1";//需要拆箱需走PDA拆垛 } } if (unstackingMode2 == "0")//机器人拆垛 { toLocation = loadingAddre;//装车口 } else //PDA拆垛 { toLocation = outMode;//出库口 } #endregion // 储位号 var locateNo = outStockDetail.First(m => m.PalletNo == item.PalletNo).LocatNo; #region 判断 //判断托盘是否在库内 if (string.IsNullOrWhiteSpace(locateNo)) { //判断托盘是否在入库中 var imBl = com.GetImTask(item.PalletNo); if (imBl != null) { flagList.Add(4); continue; } var de = outStockDetail.First(m => m.SkuNo == item.SkuNo && m.LotNo == item.LotNo && m.PalletNo == item.PalletNo); //判断是否是已经出过库又回库(状态为待拣货的 1)平库? if (de != null && de.WareHouseNo == "W02") { item.Status = "1"; // 出库分配信息状态改为正在执行 item.OutMode = outMode;//出库口 Db.Updateable(item).ExecuteCommand(); 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 notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice2.Status == "0" || notice2.Status == "1" || notice2.Status == "2") { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList(); if (detailList.Count(m => m.Qty >= m.AllotQty) > 0) { notice2.Status = "3"; //变更状态为正在执行 Db.Updateable(notice2).ExecuteCommand(); } } flagList.Add(0); continue; } if (item.Status == "0") { //如果不在仓库内,当前分配信息直接更新出库完成 item.Status = "2";//状态 item.OutMode = outMode;//出库口 Db.Updateable(item).ExecuteCommand(); 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 notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice2.Status == "0" || notice2.Status == "1" || notice2.Status == "2") { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList(); if (detailList.Count(m => m.Qty >= m.AllotQty) > 0) { notice2.Status = "3"; //变更状态为正在执行 Db.Updateable(notice2).ExecuteCommand(); } } } flagList.Add(0); 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") //有物品 { #region 添加出库任务 if (locate.Depth == "01") //深度为1 { var taskNo = new Common().GetMaxNo("TK"); var exTask = new LogTask //出库任务 { TaskNo = taskNo, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = locate.LocatNo,//起始位置 EndLocat = toLocation,//outMode,//目标位置 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 + "到" + toLocation + "的出库任务", //关键信息 }; Db.Insertable(exTask).ExecuteCommand(); logTaskList.Add(exTask); outDto1.Add(new OutCommandDto() { PalletNo = item.PalletNo,//托盘号 StartLocate = locate.LocatNo, // 起始位置 StartRoadway = locate.RoadwayNo,//其实巷道 EndLocate = toLocation,//outMode, // 目标位置 TaskNo = exTask.TaskNo, // 任务号 TaskType = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1 }); taskNoStr = exTask.TaskNo; } 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 = com.MoveAddress(slotBefore.LocatNo, slotBefore.RoadwayNo, item.SkuNo); //当前移库库位的储位信息 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,//托盘号 StartLocate = stockNew.LocatNo, // 起始位置 EndLocate = newSlot, // 目标位置 EndRoadway = locatey.RoadwayNo, // 目标巷道 TaskNo = exYkTask.TaskNo, // 任务号 TaskType = "2",// 任务类型 (移库) OutMode = "", //目标地址 Order = 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 = toLocation,//目标位置 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,//托盘号 StartLocate = stockNew.LocatNo, // 起始位置 EndLocate = toLocation, // 目标位置 EndRoadway = "", // 目标巷道 TaskNo = exYkTask1.TaskNo, // 任务号 TaskType = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 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 = toLocation,//目标位置 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(); logTaskList.Add(exTask1); outDto2.Add(new OutCommandDto() { StartRoadway = locate.RoadwayNo, //起始巷道 PalletNo = item.PalletNo,//托盘号 StartLocate = locate.LocatNo, // 起始位置 EndLocate = toLocation, // 目标位置 EndRoadway = locate.RoadwayNo, //目标巷道 TaskNo = exTask1.TaskNo, // 任务号 TaskType = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1, }); taskNoStr = exTask1.TaskNo; #endregion } #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(); } var notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice2.Status == "0" || notice2.Status == "1" || notice2.Status == "2") { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList(); if (detailList.Count(m => m.Qty >= m.AllotQty) > 0) { notice2.Status = "3"; //变更状态为正在执行 Db.Updateable(notice2).ExecuteCommand(); } } } locate.Status = "3"; //要出库的储位改变状态 正在出库 Db.Updateable(locate).ExecuteCommand(); item.TaskNo = taskNoStr; // 出库分配信息中更新任务号 item.Status = "1"; // 出库分配信息状态改为正在执行 item.UnstackingMode = unstackingMode2;//拆垛方式 item.OutMode = unstackingMode2 == "1" ? outMode : "";//出库口 item.LoadingAddre = unstackingMode2 == "0" ? loadingAddre : "";//装车口 Db.Updateable(item).ExecuteCommand(); #endregion flagList.Add(0); } else if (locate.Status == "3") //出库中 { #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(); } var notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice2.Status == "0" || notice2.Status == "1" || notice2.Status == "2") { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList(); if (detailList.Count(m => m.Qty >= m.AllotQty) > 0) { notice2.Status = "3"; //变更状态为正在执行 Db.Updateable(notice2).ExecuteCommand(); } } } var taskNo = Db.Queryable().First(m => m.OrderType == "1" && m.TaskNo != item.TaskNo && m.Status == "1" && m.PalletNo == item.PalletNo); if (taskNo == null) { taskNo = logTaskList.FirstOrDefault(m => m.PalletNo == item.PalletNo);//当前有同托盘不同物料出库 } if (taskNo == null) { throw new Exception($"托盘号:{item.PalletNo},出库异常"); } item.TaskNo = taskNo.TaskNo; item.Status = "1"; // 出库分配信息状态改为正在执行 item.OutMode = unstackingMode2 == "1" ? taskNo.EndLocat : "";//出库口 item.LoadingAddre = unstackingMode2 == "0" ? taskNo.EndLocat : "";//装车口 Db.Updateable(item).ExecuteCommand(); flagList.Add(0); #endregion } else if (locate.Status == "5") //移出中 { flagList.Add(1); } } //if (noticeList.Count(m => m.Status != "3") > 0) //{ // throw new Exception("波次单下发出库有误,出库单含有不是正在执行的"); //} wave.Status = "3"; wave.UpdateTime = DateTime.Now; wave.UpdateUser = userId; Db.Updateable(wave).ExecuteCommand(); outDto1.AddRange(moveDto); outDto1.AddRange(outDto2); //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "波次管理", waveNo, "出库", $"点击出库按钮波次单号为:{waveNo}的波次单", userId); Db.CommitTran(); str = string.Empty; if (flagList.Count(m => m == 0) > 0) { str += "0.下发成功、"; } if (flagList.Count(m => m == 1) > 0) { str += "1.当前要出库的储位正在移出、"; } if (flagList.Count(m => m == 2) > 0) { str += "2.出库的托盘储位信息错误(在储位表中未查询到)、"; } if (flagList.Count(m => m == 3) > 0) { str += "4.储位损坏不能出库、"; } if (flagList.Count(m => m == 4) > 0) { str += "3.要出库的托盘正在入库、"; } 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.StatusCode == 0) //{ // //更改任务的发送返回时间// // new TaskServer().EditTaskIssueOk(list2, time1, time2); // str += "下发成功"; //} //if (wcsModel.StatusCode == -1) //{ // new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.Msg); // throw new Exception(wcsModel.Msg); //} } catch (Exception ex) { throw new Exception(ex.Message); } } return outDto1; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } #endregion } catch (Exception e) { throw new Exception(e.Message); } } /// /// 判断出库是否需要拆箱 /// /// /// public string WaveIsNeedUnpack(string waveNo) { string result = "0";//是否需要拆箱,0:否 1:是 if (string.IsNullOrEmpty(waveNo)) { throw new Exception("未找到对应波次单!"); } try { var wave = Db.Queryable().First(w => w.IsDel == "0" && w.WaveNo == waveNo); if (wave == null) { throw new Exception("未找到对应出波次单!"); } var noticeList = Db.Queryable().Where(w => w.IsDel == "0" && w.WaveNo == waveNo).ToList(); if (noticeList.Count == 0) { throw new Exception("未找到对应出库单!"); } var soList = noticeList.Select(m => m.SONo).ToList(); //物料编码表 var skuList = Db.Queryable().Where(w => w.IsDel == "0"); //包装表 var packagList = Db.Queryable().Where(w => w.IsDel == "0"); //出库分配信息 var allotList = Db.Queryable().Where(w => w.IsDel == "0" && soList.Contains(w.SONo)).ToList(); foreach (var item in allotList) { var skuInfo = skuList.First(w => w.SkuNo == item.SkuNo); if (skuInfo == null) { throw new Exception("物料信息不存在!"); } var packagInfo = packagList.First(w => w.PackagNo == skuInfo.PackagNo); if (packagInfo == null) { throw new Exception("包装信息不存在!"); } if (packagInfo.L2Name == "箱") { if (item.Qty % (decimal)packagInfo.L2Num != 0)//能整除说明不用拆箱,不能整除说明需要拆箱 { result = "1";//需要拆箱 break; } } var boxInfo = Db.Queryable().Where(w => w.IsDel == "0" && w.PalletNo == item.PalletNo && w.BitBoxMark == "1").ToList(); if (boxInfo != null)//托盘上有零箱需要拆箱 { result = "1";//需要拆箱 break; } } return result; } catch (Exception ex) { throw new Exception(ex.Message); } } #region 数据归档 //获取波次单信息-数据归档 public List GetArchivingWaveMageList(string waveNo, string status, string lotNo, int? logisticsId, int page, int limit, out int count) { string sqlString = string.Empty; string sqlCount = string.Empty; string sqlPub = string.Empty; try { sqlCount += "SELECT DISTINCT COUNT(tb1.ID) FROM ArchivingWaveMage AS tb1 "; sqlString += "SELECT DISTINCT tb1.Id,tb1.WaveNo,tb1.Status,tb1.Origin,tb1.LotNo, "; sqlString += "tb1.LotText,tb1.SupplierLot,tb1.CustomerNo,tb1.CustomerName,"; sqlString += "tb1.LogisticsId,tb2.CarrierName as LogisticsName,tb1.Address,"; sqlString += "tb3.RealName as CreateUserName,tb4.RealName as UpdateUserName,tb1.CreateTime,tb1.UpdateTime "; sqlString += " FROM ArchivingWaveMage AS tb1 "; sqlPub += "LEFT JOIN SysLogisticsInfo AS tb2 ON tb1.LogisticsId = tb2.Id "; sqlPub += "LEFT JOIN SysUserInfor AS tb3 ON tb1.CreateUser = tb3.Id "; sqlPub += "LEFT JOIN SysUserInfor AS tb4 ON tb1.UpdateUser = tb4.Id "; sqlPub += $"WHERE tb1.LotNo LIKE '%{lotNo}%' and tb1.IsDel = '0' "; if (!string.IsNullOrWhiteSpace(waveNo)) { sqlPub += $"AND tb1.WaveNo = '{waveNo}' "; } if (!string.IsNullOrWhiteSpace(status)) { sqlPub += $"AND tb1.Status = '{status}' "; } if (logisticsId != null) { sqlPub += $"AND tb1.LogisticsId = '{logisticsId}' "; } sqlCount += sqlPub; sqlPub += " order by tb1.CreateTime desc "; if (page == 0) { page = 1; } sqlString += sqlPub + $" offset {((page - 1) * limit)} rows fetch next {limit} rows only;"; var com = new Common(); count = com.GetRowCount(sqlCount); var modelList = Db.Ado.SqlQuery(sqlString); return modelList; } catch (Exception ex) { throw ex; } } #endregion } }