using Model.InterFaceModel; using Model.ModelDto.BllSoDto; using Model.ModelVm.BllSoVm; using SqlSugar; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Linq; using System.Linq.Expressions; using System.Xml; using Model.ModelDto.DataDto; using Newtonsoft.Json; using Utility.Tools; using WMS.BLL.DataServer; 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; using Model.ModelVm; using System.Runtime.Intrinsics.X86; using ZXing.OneD; using System.Threading.Tasks; using System.Diagnostics; using System.Drawing.Drawing2D; using Model.ModelDto.LogDto; namespace WMS.BLL.BllSoServer { public class ExportNoticeServer : DbHelper, IExportNoticeServer { private static readonly SqlSugarScope Db = DataContext.Db; private readonly object IssueOutLock = new object(); public ExportNoticeServer() : base(Db) { } #region 上游接口 /* /// /// 创建出库单据--20240611不能用重写 /// /// /// public bool ErpAddExportNotice(SoInfo model) { try { if (string.IsNullOrEmpty(model.SoType)) { throw new Exception("单据类型不可为空!"); } if (string.IsNullOrEmpty(model.Customer)) { throw new Exception("客户不可为空!"); } if (string.IsNullOrEmpty(model.OrderCode)) { throw new Exception("系统单号不可为空!"); } if (model.SoDetails.Count <= 0) { throw new Exception("出库单明细不可为空!"); } var skuNos = model.SoDetails.Select(a => a.SkuNo).Distinct().ToList(); //根据物料号获取物料信息、库存明细中获取批次描述供货批次等 var skuList = Db.Queryable().Where(a => skuNos.Contains(a.SkuNo) && a.IsDel == "0").ToList(); var stockList = Db.Queryable().Where(s => skuNos.Contains(s.SkuNo) && (s.Qty - s.FrozenQty - s.LockQty) > 0).ToList(); //客户信息 var customer = Db.Queryable().First(m => m.IsDel == "0" && m.CustomerNo == model.Customer); if (customer == null) { throw new Exception("客户不可为空!"); } var logistics = Db.Queryable().First(m => m.IsDel == "0" && m.CarrierName == model.LogisticsNo); int? logisticsId = null; if (logistics != null) { logisticsId = logistics.Id; } var billNo = ""; var bl = true; do { //获取自增单据号 billNo = new Common().GetMaxNo("SO"); var no = billNo; bl = Db.Queryable().Any(m => m.SONo == no); } while (bl); Db.BeginTran();//开启事务 try { var list = new List(); //添加出库单 foreach (var d in model.SoDetails) { if (d.Qty < 1) { throw new Exception("出库数量必须大于0"); } var sku = skuList.FirstOrDefault(a => a.SkuNo == d.SkuNo); if (sku == null) { throw new Exception($"物料信息中未查询到出库物料信息:{d.SkuNo}"); } //0:成品出库、1:领料出库、3:物料取样出库、4:不合格品出库、6:代储出库、7:其他出库、 ///2:抽检出库、5:中间品出库、8:寄存出库 if (model.SoType == "0" || model.SoType == "3" || model.SoType == "4" || model.SoType == "7" ) { if (string.IsNullOrWhiteSpace(d.LotNo)) { throw new Exception("批次不可为空!"); } } //库存 List stocks; decimal q1 = 0; Dictionary dic = new Dictionary(); if (!string.IsNullOrWhiteSpace(d.LotNo)) { stocks = stockList.Where(s => s.SkuNo == d.SkuNo && s.LotNo == d.LotNo).ToList(); if (stocks.Count < 1) { throw new Exception($"总库存中未查询到出库物料信息:{d.SkuNo}"); } //判断数量 var qty = stocks.First().Qty - stocks.First().LockQty - stocks.First().FrozenQty; if (d.Qty > qty) { throw new Exception($"总库存中出库物料信息:{d.SkuNo}、{d.LotNo} 库存数量不足"); } if (qty > d.Qty - q1) { q1 += d.Qty - q1; dic.Add(stocks.First().Id, d.Qty - q1); } else { q1 += qty; dic.Add(stocks.First().Id, qty); } } else { //首先查询当前这种物料批次号为空的 stocks = stockList.Where(s => s.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(s.LotNo)).ToList(); var i = 0; if (stocks.Count > 0) { var q2 = stocks.First().Qty - stocks.First().LockQty - stocks.First().FrozenQty; if (q2 > d.Qty - q1) { q1 += d.Qty - q1; dic.Add(stocks.First().Id, d.Qty - q1); } else { q1 += q2; dic.Add(stocks.First().Id, q2); } i++ ; } //如果批次号为空的数量不够,根据批次先进先出原则查找其它批次的 if (d.Qty >= q1) { stocks = stockList.Where(m => m.SkuNo == d.SkuNo && !string.IsNullOrWhiteSpace(m.LotNo)).OrderBy(s => s.LotNo).ToList(); foreach (var demo in stocks) { if (model.SoType == "1") { if (i >= 2) { throw new Exception("领料出库单同单据同物料不允许超过3个批次混批出库"); } } else { if (i >= 1) { throw new Exception("出库单同单据同物料不允许超过2个批次混批出库"); } } if (q1 >= d.Qty) { continue; } var q2 = demo.Qty - demo.LockQty - demo.FrozenQty; if (q2 > d.Qty - q1) { q1 += d.Qty - q1; dic.Add(demo.Id, d.Qty - q1); } else { q1 += q2; dic.Add(demo.Id, q2); } i++; } } if (d.Qty > q1) { throw new Exception($"总库存中出库物料信息:{d.SkuNo} 库存数量不足"); } } foreach (var s in dic) { var st = stockList.First(a => a.Id == s.Key); var item = new BllExportNoticeDetail() { SONo = billNo, SkuNo = sku.SkuNo, SkuName = sku.SkuName, Standard = sku.Standard, LotNo = st.LotNo, LotText = st.LotText, Qty = s.Value, AllotQty = 0, FactQty = 0, CompleteQty = 0, PackagNo = sku.PackagNo, Price = sku.Price, Money = string.IsNullOrWhiteSpace(sku.Price.ToString()) ? null : sku.Price * d.Qty, IsBale = "", IsBelt = "", SupplierLot = stocks.First().SupplierLot, IsWave = "0", WaveNo = "", IsIssueLotNo = string.IsNullOrWhiteSpace(d.LotNo) ? "0" : "1", CreateUser = 0, }; list.Add(item); st.LockQty += s.Value;//锁定数量 var i = Db.Updateable(st).UpdateColumns(it => new { it.LockQty }) .ExecuteCommand(); } } var notice = new BllExportNotice() { SONo = billNo, Type = model.SoType, Status = "0", Origin = "WMS", CustomerNo = model.Customer, CustomerName = customer.CustomerName, LogisticsId = logisticsId, IsWave = "0", WaveNo = "", IsDespatch = "0", CreateUser = 0, }; var n = Db.Insertable(notice).ExecuteCommand(); var m = Db.Insertable(list).ExecuteCommand(); if (n <= 0 || m <= 0) { Db.RollbackTran(); return false; } Db.CommitTran(); //回传上游系统锁定数量信息 return true; } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } }*/ /// /// 创建出库单据 /// /// /// public SoResInfo ErpAddExportNotice(SoInfo model) { try { if (string.IsNullOrEmpty(model.SoType)) { throw new Exception("单据类型不可为空!"); } if (string.IsNullOrEmpty(model.OrderCode)) { throw new Exception("系统单号不可为空!"); } if (model.SoDetails.Count <= 0) { throw new Exception("出库单明细不可为空!"); } //返回信息 SoResInfo result = new SoResInfo(); var skuNos = model.SoDetails.Select(a => a.SkuNo).Distinct().ToList(); //根据物料号获取物料信息 var skuList = Db.Queryable().Where(a => skuNos.Contains(a.SkuNo) && a.IsDel == "0").ToList(); //获取库存明细 var stockDetailList = Db.Queryable().Where(s => skuNos.Contains(s.SkuNo) && (s.Qty - s.FrozenQty - s.LockQty) > 0 && s.InspectStatus == "1").ToList(); //获取库存 var stockList = Db.Queryable().Where(s => skuNos.Contains(s.SkuNo) && (s.Qty - s.FrozenQty - s.LockQty) > 0).ToList(); string CustomerName = string.Empty; if (!string.IsNullOrEmpty(model.Customer)) { //客户信息 var customer = Db.Queryable().First(m => m.IsDel == "0" && m.CustomerNo == model.Customer); if (customer == null) { throw new Exception("客户信息不存在!"); } CustomerName = customer.CustomerName; } //承运商信息 var logistics = Db.Queryable().First(m => m.IsDel == "0" && m.CarrierName == model.LogisticsNo); int? logisticsId = null; if (logistics != null) { logisticsId = logistics.Id; } var billNo = ""; var bl = true; do { //获取自增单据号 billNo = new Common().GetMaxNo("SO"); var no = billNo; bl = Db.Queryable().Any(m => m.SONo == no); } while (bl); List soDetailList = new List(); //开启事务 Db.BeginTran(); try { var list = new List(); //添加出库单 foreach (var d in model.SoDetails) { if (d.Qty < 1) { throw new Exception("出库数量必须大于0"); } var sku = skuList.FirstOrDefault(a => a.SkuNo == d.SkuNo); if (sku == null) { throw new Exception($"物料信息中未查询到出库物料信息:{d.SkuNo}"); } //0:成品出库、1:领料出库、3:物料取样出库、4:不合格品出库、6:代储出库、7:其他出库、 ///2:抽检出库、5:中间品出库、8:寄存出库 if (model.SoType == "0" || model.SoType == "3" || model.SoType == "4" || model.SoType == "7") { if (string.IsNullOrWhiteSpace(d.LotNo)) { throw new Exception("批次不可为空!"); } } //库存明细 List stockDetails; //指定批次 if (!string.IsNullOrWhiteSpace(d.LotNo)) { stockDetails = stockDetailList.Where(s => s.SkuNo == d.SkuNo && s.LotNo == d.LotNo).ToList(); if (stockDetails.Count < 1) { throw new Exception($"库存中未查询到出库物料信息:{d.SkuNo}"); } //判断数量 var qty = stockDetails.Sum(s => s.Qty - s.FrozenQty - s.LockQty); if (d.Qty > qty) { throw new Exception($"总库存中出库物料信息:{d.SkuNo}、{d.LotNo} 库存数量不足"); } //库存信息 var stockInfo = stockList.First(w => w.SkuNo == d.SkuNo && w.LotNo == d.LotNo); if (stockInfo == null) { throw new Exception($"总库存中未查询到出库物料信息:{d.SkuNo}"); } //判断总库存数量 if (d.Qty > stockInfo.Qty - stockInfo.FrozenQty - stockInfo.LockQty) { throw new Exception($"总库存中出库物料信息:{d.SkuNo}、{d.LotNo} 库存数量不足"); } //添加出库单明细 var noticeDetail = new BllExportNoticeDetail() { SONo = billNo, SkuNo = sku.SkuNo, SkuName = sku.SkuName, Standard = sku.Standard, LotNo = d.LotNo, LotText = stockInfo.LotText, Qty = d.Qty, AllotQty = 0, FactQty = 0, CompleteQty = 0, PackagNo = sku.PackagNo, Price = sku.Price, Money = string.IsNullOrWhiteSpace(sku.Price.ToString()) ? null : sku.Price * d.Qty, IsBale = "", IsBelt = "", SupplierLot = stockInfo.SupplierLot, IsWave = "0", WaveNo = "", IsIssueLotNo = string.IsNullOrWhiteSpace(d.LotNo) ? "0" : "1", IsMixBox = d.IsMixBox, OrderDetailCode = d.OrderDetailCode, CreateUser = 0, }; list.Add(noticeDetail); //更新库存锁定数量 stockInfo.LockQty += d.Qty; var i = Db.Updateable(stockInfo).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); SoDetailInfo soDetail = new SoDetailInfo(); soDetail.OrderDetailCode = d.OrderDetailCode; soDetail.LockQty = d.Qty; soDetail.LotNo = d.LotNo; soDetailList.Add(soDetail); } else//未指定批次 { Dictionary dic = new Dictionary(); decimal q1 = 0; //首先查询当前这种物料批次号为空的 stockDetails = stockDetailList.Where(s => s.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(s.LotNo)).ToList(); if (stockDetails.Count > 0) { q1 = (decimal)stockDetails.Sum(s => s.Qty - s.FrozenQty - s.LockQty); //库存信息 var stockInfo = stockList.FirstOrDefault(w => w.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(w.LotNo)); if (stockInfo != null) { var q2 = stockInfo.Qty - stockInfo.FrozenQty - stockInfo.LockQty; if (q2 < q1) { q1 = q2; } if (d.Qty > q1) { dic.Add(stockInfo.Id, q1); } else { dic.Add(stockInfo.Id, d.Qty); } } } //如果批次号为空的数量不够,根据批次先进先出原则查找其它批次的 if (d.Qty > q1) { stockDetails = stockDetailList.Where(m => m.SkuNo == d.SkuNo && !string.IsNullOrWhiteSpace(m.LotNo)).OrderBy(s => s.LotNo).ToList(); foreach (var demo in stockDetails) { if (q1 >= d.Qty) { break; } var q2 = demo.Qty - demo.FrozenQty - demo.LockQty; //库存信息 var stockInfo = stockList.FirstOrDefault(w => w.SkuNo == d.SkuNo && w.LotNo == demo.LotNo); if (stockInfo == null) { continue; } decimal q4 = 0; if (dic.ContainsKey(stockInfo.Id)) { q4 = dic[stockInfo.Id]; } var q3 = stockInfo.Qty - stockInfo.FrozenQty - stockInfo.LockQty - q4; if (q3 < q2) { q2 = q3; } if (q2 > d.Qty - q1) { if (!dic.ContainsKey(stockInfo.Id)) { dic.Add(stockInfo.Id, d.Qty - q1); } else { //更新值 dic[stockInfo.Id] += d.Qty - q1; } q1 += d.Qty - q1; } else { if (!dic.ContainsKey(stockInfo.Id)) { dic.Add(stockInfo.Id, (decimal)q2); } else { //更新值 dic[stockInfo.Id] = dic[stockInfo.Id] + (decimal)q2; } q1 += (decimal)q2; } } } if (d.Qty > q1) { throw new Exception($"总库存中出库物料信息:{d.SkuNo} 库存数量不足"); } foreach (var s in dic) { var st = stockList.First(a => a.Id == s.Key); var item = new BllExportNoticeDetail() { SONo = billNo, OrderDetailCode = d.OrderDetailCode, SkuNo = sku.SkuNo, SkuName = sku.SkuName, Standard = sku.Standard, LotNo = st.LotNo, LotText = st.LotText, Qty = s.Value, AllotQty = 0, FactQty = 0, CompleteQty = 0, PackagNo = sku.PackagNo, Price = sku.Price, Money = string.IsNullOrWhiteSpace(sku.Price.ToString()) ? null : sku.Price * d.Qty, IsBale = "", IsBelt = "", SupplierLot = st.SupplierLot, IsWave = "0", WaveNo = "", IsIssueLotNo = string.IsNullOrWhiteSpace(d.LotNo) ? "0" : "1", IsMixBox = d.IsMixBox, CreateUser = 0, }; list.Add(item); st.LockQty += s.Value;//锁定数量 var i = Db.Updateable(st).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); SoDetailInfo soDetail = new SoDetailInfo(); soDetail.OrderDetailCode = d.OrderDetailCode; soDetail.LockQty = s.Value; soDetail.LotNo = st.LotNo; soDetailList.Add(soDetail); } } } var notice = new BllExportNotice() { SONo = billNo, OrderCode=model.OrderCode, Type = model.SoType, Status = "0", Origin = "WMS", CustomerNo = model.Customer, CustomerName = CustomerName, LogisticsId = logisticsId, IsWave = "0", WaveNo = "", IsDespatch = "0", CreateUser = 0, }; var n = Db.Insertable(notice).ExecuteCommand(); var m = Db.Insertable(list).ExecuteCommand(); if (n <= 0 || m <= 0) { Db.RollbackTran(); throw new Exception("操作失败"); } Db.CommitTran(); //回传上游系统锁定数量信息 result.Success = "0"; result.Message = "操作成功"; result.SoDetails = soDetailList; return result; } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } //回传出库单 public bool FinishSo(int id, string url, int userId) { try { var notice = Db.Queryable().First(m => m.Id == id && m.IsDel == "0"); if (notice == null) { throw new Exception("未查询到单据信息"); } if (notice.Status != "5") { throw new Exception("复核失败,单据非关闭状态"); } var detail = Db.Queryable().Where(m => m.SONo == notice.SONo && m.IsDel == "0").ToList(); if (detail.Count == 0) { throw new Exception("未查询到单据明细信息"); } if (userId == notice.UpdateUser) { throw new Exception("复核失败,复核人员和关闭订单人员不能相同!"); } var list = new List(); foreach (var d in detail) { var item = new SoDetail() { SkuNo = d.SkuNo, LotNo = d.LotNo, Qty = (decimal)d.CompleteQty }; list.Add(item); } var soInfo = new SoInfo() { OrderCode = notice.OrderCode, SoDetails = list }; #region 通过接口发送至erp //系统对接后放开 /*var jsonData = JsonConvert.SerializeObject(soInfo); var response = HttpHelper.DoPost(url, jsonData, "出库单完成上传", "ERP"); var obj = JsonConvert.DeserializeObject(response);//解析返回数据 if (obj.Success != 0) { throw new Exception("上传失败" + obj.Message); }*/ #endregion notice.Status = "6"; notice.CheckTime = DateTime.Now; notice.CheckUser = userId; Db.Updateable(notice).ExecuteCommand(); new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "复核", $"复核了单据号为{notice.SONo}的单据信息", userId); return true; } catch (Exception e) { throw new Exception(e.Message); } } //生产叫料 public bool MESProductionCall(ProductionCallVm model) { try { //验证是否备料完成 var notice = Db.Queryable().First(m=>m.IsDel == "0" && m.OrderCode == model.OrderCode); if (notice == null) { throw new Exception("未查询到此工单号"); } var noticeDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == notice.SONo).ToList(); var task = Db.Queryable().First(m => m.SoNo == notice.SONo); if (task == null) { throw new Exception("此工单还未备料"); } if (task.Status != 2) { throw new Exception("此工单未备料完成"); } var call = Db.Queryable().First(m => m.IsDel == "0" && m.PutInLocation == model.PutInLocation && m.OrderCode == model.OrderCode); if (call != null) { throw new Exception("当前单据物料在此投料口叫料信息已收到,无需重复下发"); } //判断当前投料口是否有其它工单投料 var call2 = Db.Queryable().First(m => m.IsDel == "0" && m.PutInLocation == model.PutInLocation && m.OrderCode != model.OrderCode ); if (call2 != null) { throw new Exception("此投料口有其它单据物料叫料信息"); } //创建任务 var locateList = Db.Queryable().Where(m => m.AreaNo == model.PutInLocation && m.Flag == "0").ToList(); if (locateList.Count(m => m.Status != "0" || !string.IsNullOrWhiteSpace(m.SkuNo)) > 0) { throw new Exception("当前投料口工位有不能运料的工位,请通知管理员查看"); } try { Db.BeginTran(); var proCallList = new List(); foreach (var item in noticeDetail) { var proCall = new BllProductionCallTask() { PutInLocation = model.PutInLocation, OrderCode = notice.SONo, SkuNo = model.SkuNo, CreateUser = 1 }; Db.Insertable(proCall).ExecuteCommand(); proCallList.Add(proCall); } var list = new List(); foreach (var pro in proCallList) { foreach (var item in locateList) { //获取备好料的托盘信息 var allotList = Db.Queryable().Where(m => m.IsDel == "0" && m.Status == "2" && m.SONo == notice.SONo && m.SkuNo == pro.SkuNo && !list.Contains(m.Id)).Select(m => m.PalletNo).ToList(); var stockDetail = Db.Queryable().Where(m => allotList.Contains(m.PalletNo)).OrderBy(m => m.LocatNo).First(); var taskNo = new Common().GetMaxNo("TK"); //出库任务 var exTask = new LogTask { TaskNo = taskNo, Sender = "WMS", Receiver = "AGV", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = stockDetail.LocatNo,//起始位置 EndLocat = item.LocatNo,//目标位置 PalletNo = stockDetail.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = "从" + stockDetail.LocatNo + "到" + item.LocatNo + "的出库任务", //关键信息 FinishIsPick = "1" }; Db.Insertable(exTask).ExecuteCommand(); //更改分配表的任务号列 var allot = Db.Queryable().First(m=>m.IsDel == "0" && m.Status =="2" && m.SONo == notice.SONo && m.StockId == stockDetail.Id); allot.TaskNo = taskNo; Db.Updateable(allot).ExecuteCommand(); list.Add(allot.Id); item.Status = "4"; item.SkuNo = stockDetail.SkuNo; item.PalletNo = stockDetail.PalletNo; Db.Updateable(item).ExecuteCommand(); var locate = Db.Queryable().First(m=>m.LocatNo == stockDetail.LocatNo); locate.Status = "5"; Db.Updateable(locate).ExecuteCommand(); break; } } Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } return true; } catch (Exception e) { throw new Exception(e.Message); } } #endregion #region JC34 #region 基础功能 public async Task> GetExportNoticeList(GetExportNoticeVm model, RefAsync count) { var strList = new List(); if (!string.IsNullOrWhiteSpace(model.LotNo)) { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.LotNo.Contains(model.LotNo.Trim())).Select(m => m.SONo).Distinct().ToList(); strList = detailList; } Expression> item = Expressionable.Create() .AndIF(!string.IsNullOrWhiteSpace(model.No), it => it.SONo.Contains(model.No.Trim())) .AndIF(!string.IsNullOrWhiteSpace(model.Type), it => it.Type == model.Type) .AndIF(!string.IsNullOrWhiteSpace(model.Status), it => it.Status == model.Status) .AndIF(model.LogisticsId != null, it => it.LogisticsId == model.LogisticsId) .AndIF(!string.IsNullOrWhiteSpace(model.IsWave), it => it.IsWave == model.IsWave) .AndIF(!string.IsNullOrWhiteSpace(model.IsDespatch), it => it.IsDespatch == model.IsDespatch) .AndIF(!string.IsNullOrWhiteSpace(model.WaveNo), it => it.WaveNo.Contains(model.WaveNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(model.LotNo), it => strList.Contains(it.SONo)) .ToExpression();//注意 这一句 不能少 var data = await 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) .LeftJoin((a, b, c, d, e) => a.CheckUser == e.Id) .LeftJoin((a, b, c, d, e,f) => a.WareHouseNo == f.WareHouseNo) .Select((a, b, c, d, e,f) => new ExportNoticeDto() { Id = a.Id, SONo = a.SONo, Type = a.Type, Status = a.Status, WareHouseName = f.WareHouseName, Origin = a.Origin, CustomerNo = a.CustomerNo, CustomerName = a.CustomerName, LotNo = a.LotNo, LotText = a.LotText, SupplierLot = a.SupplierLot, LogisticsId = a.LogisticsId, LogisticsName = b.CarrierName, IsWave = a.IsWave, WaveNo = a.WaveNo, IsDespatch = a.IsDespatch, Demo = a.Demo, CreateUserName = c.RealName, UpdateUserName = c.RealName, CreateTime = a.CreateTime, UpdateTime = a.UpdateTime, CheckUserName = e.RealName, CheckTime = a.CheckTime }) .OrderByDescending(a => a.CreateTime) .ToPageListAsync(model.Page, model.Limit, count); return data; } //获取添加/编辑出库单时选择物料明细信息 public List GetStockGroupList(string house, string type, string ownerNo, string msg) { try { if (string.IsNullOrEmpty(house)) { throw new Exception("请选择出库仓库"); } if (string.IsNullOrEmpty(type)) { throw new Exception("请选择出库单类型"); } if (type == "6" && string.IsNullOrEmpty(ownerNo)) { throw new Exception("代储单据请选择货主"); } var plnList = new List() { "100099" }; var skuStrList = new List(); var sku = Db.Queryable().Where(m => m.IsDel == "0" && !plnList.Contains(m.SkuNo)); //排除空托盘的物料集合 string skuType = string.Empty; string inspectStatus = string.Empty; switch (type)//0:原料 1:包材 2:成品 3:耗材 4:半成品 { case "0"://成品出库 if (house !="W01") { throw new Exception("成品出库只能选择成品库"); } skuType = "(2)"; inspectStatus = "1"; break; case "1"://领料出库 if (house != "W02") { throw new Exception("领料出库只能选择原料库"); } skuType = "(0,1,3)"; inspectStatus = "1"; break; case "2"://抽检出库 if (house == "W01") { skuType = "(2)"; } if (house == "W02") { skuType = "(0,1,3)"; } inspectStatus = "0,1,2"; break; case "3"://物料取样出库 if (house == "W01") { skuType = "(2)"; } if (house == "W02") { skuType = "(0,1,3)"; } inspectStatus = "0"; break; case "4"://不合格品出库 if (house == "W01") { skuType = "(2)"; } if (house == "W02") { skuType = "(0,1,3)"; } inspectStatus = "2"; break; case "5"://中间品出库 skuType = "(4)"; inspectStatus = "0,1"; break; case "6"://代储出库 skuType = "(2)"; inspectStatus = "0,1"; break; case "7"://其它出库 if (house == "W01") { skuType = "(2)"; } if (house == "W02") { skuType = "(0,1,3,4)"; } inspectStatus = "0,1"; break; case "8"://寄存出库 if (house == "W01") { skuType = "(2)"; } if (house == "W02") { skuType = "(0,1,3)"; } inspectStatus = "0,1"; break; case "9"://生产领料出库 if (house != "W02") { throw new Exception("生产领料出库只能选择原料库"); } skuType = "(0,1,3)"; inspectStatus = "1"; break; default: //其它出库 throw new Exception("单据类型错误"); } var skuList = sku.Where(m => skuType.Contains(m.Type)).ToList(); if (skuList.Count == 0) { throw new Exception("未查到对应出库类型的物料"); } if (type == "6") { skuList = skuList.Where(m => string.IsNullOrWhiteSpace(m.PackagNo)).ToList(); } if (type != "8") { skuList = skuList.Where(m => m.SkuNo != "100088").ToList(); } else { skuList = skuList.Where(m => m.SkuNo == "100088").ToList(); } skuStrList = skuList.Select(m => m.SkuNo).ToList(); var stockRst = new StockServer(); var stockDetailRst = new StockDetailServer(); Expression> item = Expressionable.Create() .And(it => it.WareHouseNo == house) .AndIF(!string.IsNullOrWhiteSpace(inspectStatus), it => inspectStatus.Contains(it.InspectStatus)) .And(m => skuStrList.Contains(m.SkuNo)) .AndIF(type == "6", m => m.OwnerNo == ownerNo)//代储出库需要关联货主 .AndIF(!string.IsNullOrWhiteSpace(msg), it => (it.SkuNo.Contains(msg) || it.SkuName.Contains(msg) || it.LotNo.Contains(msg))) .And(it => (it.Qty - it.LockQty - it.FrozenQty) > 0) .And(it => (it.Status == "0" || it.Status == "1")) .ToExpression();//注意 这一句 不能少 //库存明细 var stockDetail = stockDetailRst.GetAllWhereAsync(item).GroupBy(m => new { m.SkuNo, m.SkuName, m.LotNo, m.Standard, }).Select(it => new ExStockInfoDto { SkuNo = it.SkuNo, SkuName = it.SkuName, LotNo = it.LotNo, Standard = it.Standard, Qty = SqlFunc.AggregateSumNoNull(it.Qty - it.LockQty - it.FrozenQty), }).ToList(); //库存总表 var stock = stockRst.GetAllAsync().Select(it => new ExStockInfoDto { SkuNo = it.SkuNo, SkuName = it.SkuName, LotNo = it.LotNo, Standard = it.Standard, //Qty = type == "4" ? it.Qty : it.Qty - it.LockQty - it.FrozenQty, Qty = it.Qty - it.LockQty - it.FrozenQty, }).ToList(); foreach (var l in stockDetail.ToArray()) { var fq = stock.Where(s => s.SkuNo == l.SkuNo); if (!string.IsNullOrWhiteSpace(l.LotNo)) { fq = fq.Where(s => s.LotNo == l.LotNo); } else { fq = fq.Where(s => string.IsNullOrWhiteSpace(s.LotNo)); } var f = fq.FirstOrDefault(); if (f == null) { throw new Exception("库存信息错误,请核实"); } if (f.Qty != null && f.Qty.Value < l.Qty) { l.Qty = f.Qty.Value; } if (l.Qty <= 0) { stockDetail.Remove(l); } } return stockDetail; } catch (Exception e) { throw new Exception(e.Message); } } //WMS添加出库单 public bool AddExportNotice(AddEditExportNoticeVm model, int userId) { try { if (model == null || model.Detail.Count == 0) { throw new Exception("参数异常"); } var skuNos = model.Detail.Select(a => a.SkuNo).Distinct().ToList(); //根据物料号获取物料信息、库存明细中获取批次描述供货批次等 var skuList = Db.Queryable().Where(a => skuNos.Contains(a.SkuNo) && a.IsDel == "0").ToList(); switch (model.WareHouseNo) { case "W01"://成品库 if (skuList.Any(m=>m.Type !="2")) { throw new Exception("仓库与出库物料不符"); } break; case "W02"://原料库 if (skuList.Any(m => m.Type == "2")) { throw new Exception("仓库与出库物料不符"); } break; default: throw new Exception("仓库号错误"); } var stockList = Db.Queryable().Where(s => skuNos.Contains(s.SkuNo) && (s.Qty - s.FrozenQty - s.LockQty) > 0).ToList(); //var palletList = contextDb.Queryable().Where(s => skuNos.Contains(s.SkuNo) && (s.Qty - s.FrozenQty - s.LockQty) > 0).ToList(); //客户信息 var customer = Db.Queryable().Where(m => m.IsDel == "0" && m.CustomerNo == model.CustomerNo).ToList(); var billNo = ""; var bl = true; do { //获取自增单据号 billNo = new Common().GetMaxNo("SO"); var no = billNo; bl = Db.Queryable().Any(m => m.SONo == no); } while (bl); Db.BeginTran();//开启事务 try { var list = new List(); //添加出库单 foreach (var d in model.Detail) { if (d.Qty < 1) { throw new Exception("出库数量必须大于0"); } var sku = skuList.FirstOrDefault(a => a.SkuNo == d.SkuNo); if (sku == null) { throw new Exception($"物料信息中未查询到出库物料信息:{d.SkuNo}"); } //0:成品出库、1:领料出库、2:抽检出库、4:不合格品出库、7:其他出库、9生产领料出库 ///3:物料取样出库、5:中间品出库、6:代储出库、8:寄存出库 if (model.Type == "0" || model.Type == "2" || model.Type == "4" || model.Type == "7") { if (string.IsNullOrWhiteSpace(d.LotNo)) { throw new Exception("批次不可为空!"); } } //if (model.Type == "1") //{ // if (list.Count(m=>m.SkuNo == d.SkuNo)>=2) // { // throw new Exception("领料出库单同单据同物料不允许超过3个批次混批出库"); // } //} //else //{ // if (list.Count(m => m.SkuNo == d.SkuNo) >= 1) // { // throw new Exception("出库单同单据同物料不允许超过2个批次混批出库"); // } //} //库存 List stocks; decimal q1 = 0; Dictionary dic = new Dictionary(); if (!string.IsNullOrWhiteSpace(d.LotNo)) { stocks = stockList.Where(s => s.SkuNo == d.SkuNo && s.LotNo == d.LotNo).ToList(); } else { stocks = stockList.Where(s => s.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(s.LotNo)).ToList(); } if (stocks.Count < 1) { throw new Exception($"总库存中未查询到出库物料信息:{d.SkuNo}"); } //判断数量 var qty = stocks.First().Qty - stocks.First().LockQty - stocks.First().FrozenQty; if (d.Qty > qty) { throw new Exception($"总库存中出库物料信息:{d.SkuNo}、{d.LotNo} 库存数量不足"); } var item = new BllExportNoticeDetail() { SONo = billNo, SkuNo = sku.SkuNo, SkuName = sku.SkuName, Standard = sku.Standard, LotNo = d.LotNo, LotText = "", Status = "0", Qty = d.Qty, AllotQty = 0, FactQty = 0, CompleteQty = 0, PackagNo = sku.PackagNo, Price = sku.Price, Money = string.IsNullOrWhiteSpace(sku.Price.ToString()) ? null : sku.Price * d.Qty, IsBale = d.IsBale, IsBelt = d.IsBelt, SupplierLot = stocks.First().SupplierLot, IsWave = "0", WaveNo = "", CreateUser = userId, }; list.Add(item); stocks.First().LockQty += d.Qty;//锁定数量 var i = Db.Updateable(stocks.First()).UpdateColumns(it => new { it.LockQty }) .ExecuteCommand(); //foreach (var s in dic) //{ // var st = stockList.First(m => m.Id == s.Key); // st.LockQty += s.Value;//锁定数量 // var i = Db.Updateable(st).UpdateColumns(it => new { it.LockQty }) // .ExecuteCommand(); //} } var notice = new BllExportNotice() { SONo = billNo, Type = model.Type, Status = "0", Origin = "WMS", CustomerNo = model.CustomerNo, CustomerName = customer.FirstOrDefault() == null ? "" : customer.First().CustomerName, LogisticsId = model.LogisticsId, IsWave = "0", WaveNo = "", IsDespatch = "0", CreateUser = userId, }; var n = Db.Insertable(notice).ExecuteCommand(); var m = Db.Insertable(list).ExecuteCommand(); if (n <= 0 || m <= 0) { Db.RollbackTran(); return false; } //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", billNo, "添加", $"添加了单据号为{billNo}的单据信息", userId); Db.CommitTran(); return true; } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } catch (Exception e) { throw new Exception(e.Message); } } //获取编辑出库单及明细信息 public EditExportNotifyDto GetEditExportNotice(string code) { try { var notify = Db.Queryable().Where(m => m.SONo == code && m.IsDel == "0").ToList().FirstOrDefault(); if (notify == null) { throw new Exception($"未查询到{code}的单据信息"); } var detail = Db.Queryable().Where(m => m.SONo == code && m.IsDel == "0").ToList(); var skuList = detail.Select(m => m.SkuNo).ToList(); var stock = Db.Queryable().Where(m => skuList.Contains(m.SkuNo) && m.IsDel == "0").ToList(); var model = new EditExportNotifyDto { SoNo = notify.SONo, Type = notify.Type, WareHouseNo = notify.WareHouseNo, CustomerNo = notify.CustomerNo, LogisticsId = notify.LogisticsId, //ExportWarehouseId = notify.ExportWarehouseId, }; model.Detail = new List(); DataStock s; foreach (var d in detail) { if (string.IsNullOrWhiteSpace(d.LotNo)) { s = stock.FirstOrDefault(m => m.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(m.LotNo)); } else { s = stock.FirstOrDefault(m => m.SkuNo == d.SkuNo && m.LotNo == d.LotNo); } var stockCount = 0.00m; //st.StockQuantity.Value if (s != null) { stockCount = s.Qty - s.FrozenQty - s.LockQty + d.Qty; } var dm = new SelectStockSkuDto() { SkuNo = d.SkuNo, SkuName = d.SkuName, Standard = d.Standard, LotNo = d.LotNo, Qty = stockCount, ExQty = d.Qty, IsBale = d.IsBale, IsBelt = d.IsBelt }; model.Detail.Add(dm); } return model; } catch (Exception e) { throw new Exception(e.Message); } } //修改出库单 public EditExportNotifyDto EditExportNotice(AddEditExportNoticeVm model, int userId) { try { if (model == null || model.Detail.Count == 0) { throw new Exception("参数异常"); } var notice = Db.Queryable().Where(m => m.IsDel == "0" && m.Id == model.Id).ToList().FirstOrDefault(); if (notice == null) { throw new Exception("未查询到出库单据信息"); } if (notice.Origin != "WMS" || notice.Status != "0") { throw new Exception("参数异常,请检查状态是否未等待执行或来源是否是WMS"); } //出库单明细 var noticeDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == notice.SONo).ToList(); //根据物料号获取物料信息、库存明细中获取批次描述供货批次等 var skuList = Db.Queryable().Where(a => a.IsDel == "0").ToList(); var stockList = Db.Queryable().Where(s => (s.Qty - s.FrozenQty - s.LockQty + noticeDetail[0].Qty) > 0).ToList(); var palletList = Db.Queryable().Where(s => (s.Qty - s.FrozenQty - s.LockQty + noticeDetail[0].Qty) > 0).ToList(); Db.BeginTran();//开启事务 try { if (notice.Origin == "WMS") { //删除旧 foreach (var d in noticeDetail) { var mq = model.Detail.Where(o => o.SkuNo == d.SkuNo).ToList(); if (!string.IsNullOrWhiteSpace(d.LotNo)) { mq = mq.Where(o => o.LotNo == d.LotNo).ToList(); } if (mq.Any()) //如果有这个物料及批次则跳过 { continue; } // var fl = stockList.Where(s => s.SkuNo == d.SkuNo).ToList(); DataStock fls; if (!string.IsNullOrWhiteSpace(d.LotNo)) { fls = fl.FirstOrDefault(s => s.SkuNo == d.SkuNo && s.LotNo == d.LotNo); } else { fls = fl.FirstOrDefault(s => s.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(s.LotNo)); } if (fls == null) { throw new Exception($"未找到物料{d.SkuNo}、批次{d.LotNo} 的库存信息"); } fls.LockQty -= d.Qty; d.IsDel = "1"; d.UpdateUser = userId; d.UpdateTime = DateTime.Now; Db.Updateable(d).ExecuteCommand(); Db.Updateable(fls).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); } //更新出库单 foreach (var d in model.Detail) { if (d.Qty < 1) { throw new Exception("出库数据必须大于0"); } var sku = skuList.FirstOrDefault(a => a.SkuNo == d.SkuNo); if (sku == null) { throw new Exception("出库物品为空"); } //库存 List stocks; List pallet; if (!string.IsNullOrWhiteSpace(d.LotNo)) { stocks = stockList.Where(s => s.SkuNo == d.SkuNo && s.LotNo == d.LotNo).ToList(); pallet = palletList.Where(p => p.SkuNo == d.SkuNo && p.LotNo == d.LotNo).ToList(); } else { stocks = stockList.Where(s => s.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(s.LotNo)).ToList(); pallet = palletList.Where(p => p.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(p.LotNo)).ToList(); } if (stocks.Count < 1) { throw new Exception("出库物品库存不足"); } var stock = stocks.First();//总库存 // BllExportNoticeDetail old; if (string.IsNullOrWhiteSpace(d.LotNo)) { old = noticeDetail.FirstOrDefault(o => o.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(o.LotNo)); } else { old = noticeDetail.FirstOrDefault(o => o.SkuNo == d.SkuNo && o.LotNo == d.LotNo); } //新加项 if (old == null) { //判断数量 var qty = stock.Qty - stock.LockQty - stock.FrozenQty; if (d.Qty > qty) { throw new Exception($"总库存中出库物料信息:{d.SkuNo}、{d.LotNo} 库存数量不足"); } var item = new BllExportNoticeDetail() { SONo = notice.SONo, SkuNo = sku.SkuNo, SkuName = sku.SkuName, Standard = sku.Standard, LotNo = d.LotNo, LotText = "", Status = "0", Qty = d.Qty, AllotQty = 0, FactQty = 0, CompleteQty = 0, PackagNo = sku.PackagNo, Price = sku.Price, Money = string.IsNullOrWhiteSpace(sku.Price.ToString()) ? null : sku.Price * qty, IsBale = d.IsBale, IsBelt = d.IsBelt, SupplierLot = stocks.First().SupplierLot, IsWave = "0", WaveNo = "", CreateUser = userId, }; stock.LockQty += d.Qty;//锁定数量 var m = Db.Insertable(item).ExecuteCommand(); var i = Db.Updateable(stock).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); } else if (old.Qty != d.Qty || old.IsBale != d.IsBale || old.IsBelt != d.IsBelt) { if (d.Qty > (stock.Qty - stock.FrozenQty - stock.LockQty) + old.Qty) { throw new Exception("物品库存数量不足"); } //增加 if (d.Qty > old.Qty) { stock.LockQty += d.Qty - old.Qty; } else { stock.LockQty -= old.Qty - d.Qty; } old.IsBale = d.IsBale; old.IsBelt = d.IsBelt; old.Qty = d.Qty; old.UpdateUser = userId; old.UpdateTime = DateTime.Now; var m = Db.Updateable(old).UpdateColumns(it => new { it.IsBale, it.IsBelt, it.Qty, it.UpdateUser, it.UpdateTime }).ExecuteCommand(); var i = Db.Updateable(stock).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); } } //客户信息 var customer = Db.Queryable().Where(m => m.IsDel == "0" && m.CustomerNo == model.CustomerNo).ToList().FirstOrDefault(); notice.Type = model.Type; notice.CustomerNo = model.CustomerNo; notice.CustomerName = customer == null ? "" : customer.CustomerName; notice.LogisticsId = model.LogisticsId; notice.UpdateUser = userId; notice.UpdateTime = DateTime.Now; var n = Db.Updateable(notice).ExecuteCommand(); if (n <= 0) { Db.RollbackTran(); return null; } } else //erp/mes { //删除旧 foreach (var d in noticeDetail) { var mq = model.Detail.Where(o => o.SkuNo == d.SkuNo).ToList(); if (!string.IsNullOrWhiteSpace(d.LotNo)) { mq = mq.Where(o => o.LotNo == d.LotNo).ToList(); } if (mq.Any()) //如果有这个物料及批次则跳过 { continue; } // var fl = stockList.Where(s => s.SkuNo == d.SkuNo).ToList(); DataStock fls; if (!string.IsNullOrWhiteSpace(d.LotNo)) { fls = fl.FirstOrDefault(s => s.SkuNo == d.SkuNo && s.LotNo == d.LotNo); } else { fls = fl.FirstOrDefault(s => s.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(s.LotNo)); } if (fls == null) { throw new Exception($"未找到物料{d.SkuNo}、批次{d.LotNo} 的库存信息"); } fls.LockQty -= d.Qty; d.IsDel = "1"; d.UpdateUser = userId; d.UpdateTime = DateTime.Now; Db.Updateable(d).ExecuteCommand(); Db.Updateable(fls).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); } //更新出库单 foreach (var d in model.Detail) { if (d.Qty < 1) { throw new Exception("出库数据必须大于0"); } var sku = skuList.FirstOrDefault(a => a.SkuNo == d.SkuNo); if (sku == null) { throw new Exception("出库物品为空"); } //库存 List stocks; if (!string.IsNullOrWhiteSpace(d.LotNo)) { stocks = stockList.Where(s => s.SkuNo == d.SkuNo && d.LotNo.Contains(s.LotNo)).ToList(); } else { stocks = stockList.Where(s => s.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(s.LotNo)).ToList(); } if (stocks.Count < 1) { throw new Exception("出库物品库存不足"); } var stock = stocks.First();//总库存 // BllExportNoticeDetail old; if (string.IsNullOrWhiteSpace(d.LotNo)) { old = noticeDetail.FirstOrDefault(o => o.SkuNo == d.SkuNo && string.IsNullOrWhiteSpace(o.LotNo)); } else { old = noticeDetail.FirstOrDefault(o => o.SkuNo == d.SkuNo && o.LotNo == d.LotNo); } //新加项 if (old == null) { //判断数量 var qty = stock.Qty - stock.LockQty - stock.FrozenQty; if (d.Qty > qty) { throw new Exception($"总库存中出库物料信息:{d.SkuNo}、{d.LotNo} 库存数量不足"); } var item = new BllExportNoticeDetail() { SONo = notice.SONo, SkuNo = sku.SkuNo, SkuName = sku.SkuName, Standard = sku.Standard, LotNo = d.LotNo, LotText = "", Status = "0", Qty = d.Qty, AllotQty = 0, FactQty = 0, CompleteQty = 0, PackagNo = sku.PackagNo, Price = sku.Price, Money = string.IsNullOrWhiteSpace(sku.Price.ToString()) ? null : sku.Price * qty, IsBale = d.IsBale, IsBelt = d.IsBelt, SupplierLot = stocks.First().SupplierLot, IsWave = "0", WaveNo = "", CreateUser = userId, }; stock.LockQty += d.Qty;//锁定数量 var m = Db.Insertable(item).ExecuteCommand(); var i = Db.Updateable(stock).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); } else if (old.Qty != d.Qty || old.IsBale != d.IsBale || old.IsBelt != d.IsBelt) { if (d.Qty > (stock.Qty - stock.FrozenQty - stock.LockQty) + old.Qty) { throw new Exception("物品库存数量不足"); } //增加 if (d.Qty > old.Qty) { stock.LockQty += d.Qty - old.Qty; } else { stock.LockQty -= old.Qty - d.Qty; } old.IsBale = d.IsBale; old.IsBelt = d.IsBelt; old.Qty = d.Qty; old.UpdateUser = userId; old.UpdateTime = DateTime.Now; var m = Db.Updateable(old).UpdateColumns(it => new { it.IsBale, it.IsBelt, it.Qty, it.UpdateUser, it.UpdateTime }).ExecuteCommand(); var i = Db.Updateable(stock).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); } } //客户信息 var customer = Db.Queryable().Where(m => m.IsDel == "0" && m.CustomerNo == model.CustomerNo).ToList().FirstOrDefault(); notice.Type = model.Type; notice.CustomerNo = model.CustomerNo; notice.CustomerName = customer == null ? "" : customer.CustomerName; notice.LogisticsId = model.LogisticsId; notice.UpdateUser = userId; notice.UpdateTime = DateTime.Now; var n = Db.Updateable(notice).ExecuteCommand(); if (n <= 0) { Db.RollbackTran(); return null; } //回传ERP/MES } //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "编辑", $"编辑了单据号为{notice.SONo}的单据信息", userId); Db.CommitTran(); //查询改后的单据信息 后期接口对接完后需改动回传参数 var detail = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == notice.SONo).Select(m => new SelectStockSkuDto { LotNo = m.LotNo, SkuNo = m.SkuNo, SkuName = m.SkuName, Qty = m.Qty, ExQty = decimal.Parse(m.CompleteQty.ToString()), Standard = m.Standard, IsBale = m.IsBale, IsBelt = m.IsBelt }).ToList(); var data = new EditExportNotifyDto(); data.Origin = notice.Origin; data.SoNo = notice.SONo; data.Type = notice.Type; data.CustomerNo = notice.CustomerNo; data.LogisticsId = notice.LogisticsId; data.Detail = detail; return data; } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } catch (Exception e) { throw new Exception(e.Message); } } //删除出库单 public bool DelExportNotice(int id, int userId) { try { var notice = Db.Queryable().Where(m => m.IsDel == "0" && m.Id == id).ToList().FirstOrDefault(); if (notice == null) { throw new Exception("未查询到出库单据信息"); } if (notice.Origin != "WMS" || notice.Status != "0") { throw new Exception("参数异常,请检查状态是否未等待执行或来源是否是WMS"); } //总库存信息 var stockList = Db.Queryable().ToList(); //出库单明细 var noticeDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == notice.SONo).ToList(); Db.BeginTran();//开启事务 try { foreach (var d in noticeDetail) { //总库存 var sq = stockList.Where(s => s.SkuNo == d.SkuNo); if (!string.IsNullOrWhiteSpace(d.LotNo)) { sq = sq.Where(s => s.LotNo == d.LotNo); } else { sq = sq.Where(s => string.IsNullOrWhiteSpace(s.LotNo)); } var fd = sq.FirstOrDefault(); if (fd == null) { throw new Exception($"未找到物料{d.SkuNo}、批次{d.LotNo} 的库存信息"); } fd.LockQty -= d.Qty; d.IsDel = "1"; d.UpdateUser = userId; d.UpdateTime = DateTime.Now; Db.Updateable(d).ExecuteCommand(); Db.Updateable(fd).UpdateColumns(it => new { it.LockQty }).ExecuteCommand(); } //删除出库单 notice.IsDel = "1"; notice.UpdateUser = userId; notice.UpdateTime = DateTime.Now; var n = Db.Updateable(notice).ExecuteCommand(); if (n <= 0) { Db.RollbackTran(); return false; } //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "删除", $"删除了单据号为{notice.SONo}的单据信息", userId); Db.CommitTran(); return true; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } catch (Exception e) { throw new Exception(e.Message); } } //订单关闭 public bool CloseExportNotice(int id, int userId) { try { var notice = Db.Queryable().Where(m => m.IsDel == "0" && m.Id == id).ToList().FirstOrDefault(); if (notice == null) { throw new Exception("未查询到出库单据信息"); } if (notice.Status != "4") { throw new Exception("参数异常,请检查状态是否为执行完成或订单关闭"); } //总库存信息 var stockList = Db.Queryable().ToList(); //出库单明细 var noticeDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == notice.SONo).ToList(); Db.BeginTran();//开启事务 try { //修改出库单状态 notice.Status = "5"; notice.UpdateUser = userId; notice.UpdateTime = DateTime.Now; Db.Updateable(notice).ExecuteCommand(); var skuList = noticeDetail.Select(d => d.SkuNo).ToList(); var stocks = stockList.Where(s => skuList.Contains(s.SkuNo)).ToList(); foreach (var d in noticeDetail) { //更改库存明细锁定数量 //var orders = dataContext.WmsExportOrder.Where(o => o.ExportDetailId == d.Id // && o.ExportExecuteFlag != "4" && o.ExportExecuteFlag == "3" && o.pickingType == 0).ToList(); //foreach (var o in orders) //{ // if (o.ExportQuantity > o.PickedNum) //判断拣货是否已拣完 // { // var pq = dataContext.WmsStockTray.Where(t => t.StockGoodId == o.ExportGoodsCode && t.StockStockCode == o.ExportStockCode); // if (string.IsNullOrWhiteSpace(o.ExportLotNo)) // { // pq = pq.Where(t => t.StockLotNo == null || t.StockLotNo == ""); // } // else // { // pq = pq.Where(t => t.StockLotNo == o.ExportLotNo); // } // var pallet = pq.FirstOrDefault(); // //库存托盘信息锁定数量还原为未锁定 // if (pq != null) // { // pallet.LockQuantity -= o.ExportQuantity.Value - o.PickedNum; // pallet.StockQuantity += o.ExportQuantity.Value - o.PickedNum; // } // } //} if (d.Qty != d.CompleteQty) { throw new Exception("当前单据明细中计划数量与拣货数量不符,请核实"); } #region 库存表减去锁定数量与总数量(PDA拣货的时候已经减去数量了) /*var sq = stocks.Where(s => s.SkuNo == d.SkuNo); if (!string.IsNullOrWhiteSpace(d.LotNo)) { sq = sq.Where(s => s.LotNo == d.LotNo); } else { sq = sq.Where(s => string.IsNullOrWhiteSpace(s.LotNo)); } var st = sq.FirstOrDefault(); if (st != null) { if (d.CompleteQty <= d.Qty) { st.Qty += d.Qty - d.CompleteQty.Value; } else { st.Qty -= d.CompleteQty.Value - d.Qty; } st.LockQty -= d.Qty; st.Qty -= d.Qty; //修改总库存表 Db.Updateable(st).UpdateColumns(it => new { it.Qty, it.LockQty }).ExecuteCommand(); }*/ #endregion } //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "关单", $"关闭了单据号为{notice.SONo}的单据信息", userId); Db.CommitTran(); return true; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } catch (Exception ex) { throw new Exception("关闭出库单据失败:" + ex.Message); } } public XmlNode AddExXmlStr(int id, int userId) { try { var notice = Db.Queryable().Where(m => m.IsDel == "0" && m.Id == id).ToList().FirstOrDefault(); if (notice == null) { throw new Exception("未查询到出库单据信息"); } var statusLis = new List() { "4", "5", "6" }; if (!statusLis.Contains(notice.Status)) { throw new Exception("参数异常,请检查状态是否为执行完成或订单关闭/已上传"); } //出库单明细 var comDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == notice.SONo).Select(m => m.BoxNo3).ToList(); Db.BeginTran();//开启事务 try { //Hashtable pars = new Hashtable(); //用来存放参数 var pars = new List(); //for (int i = 0; i < 10; i++) //{ // pars.Add("202203240009000479940290"); //} var dom = HttpHelper.EncodeParsToFuMa(comDetail, "ceshi", "ExInfoXml"); ////添加操作日志记录 //var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "关单", $"关闭了单据号为{notice.SONo}的单据信息", userId); Db.CommitTran(); return dom; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } catch (Exception ex) { throw new Exception("生成XML文件错误:" + ex.Message); } } #endregion #region 托盘出库 /// /// 获取托盘出库明细 /// /// 物料号 /// 物料名称 /// 托盘号 /// 批次号 /// 检验标记 /// 零托标记 /// 零托标记 /// 零托标记 /// 零托标记 /// public async Task> GetPalletNoOutList(GetPalletNoOutVm model, RefAsync count) { Expression> item = Expressionable.Create() .AndIF(!string.IsNullOrWhiteSpace(model.SkuNo), m => m.SkuNo.Contains(model.SkuNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(model.SkuName), m => m.SkuName.Contains(model.SkuName.Trim())) .AndIF(!string.IsNullOrWhiteSpace(model.PalletNo), m => m.PalletNo.Contains(model.PalletNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(model.LotNo), m => m.LotNo.Contains(model.LotNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(model.InspectMark), m => m.InspectMark == model.InspectMark) .AndIF(!string.IsNullOrWhiteSpace(model.BitPalletMark), m => m.BitPalletMark == model.BitPalletMark) .And(m => !string.IsNullOrWhiteSpace(m.WareHouseNo)) .And(a => a.Status == "0") .And(a => a.WareHouseNo == "W01") .ToExpression(); var data = await Db.Queryable().Where(item).OrderBy(m => m.LocatNo).ToPageListAsync(model.Page, model.Limit, count); //data.Select(m => m.Status == "0" && m.IsDel == "0"); return data; } //托盘出库 public List IssuePalletNoOut(string palletNo, string outMode, int userId, string url, out string str) { try { //判断托盘号是否为空 if (string.IsNullOrWhiteSpace(palletNo)) { throw new Exception($"托盘号不能为空,请核实"); } var outDtoList = new List(); //出库数据的集合 str = ""; var stockDetailList = Db.Queryable().Where(m => m.PalletNo == palletNo && m.IsDel == "0").ToList(); if (stockDetailList.Count == 0) { throw new Exception($"未在库内查询到该托盘信息"); } var stocka = Db.Queryable().First(a => a.IsDel == "0" && a.SkuNo == stockDetailList[0].SkuNo); //验证库存托盘状态 if (stockDetailList[0].Status != "0") { throw new Exception($"当前托盘未处于待分配状态,请核实!"); } //判断托盘库存信息分组后是否大于1条 var detailGroup = stockDetailList.GroupBy(m => new { m.SkuNo, m.PalletNo, m.WareHouseNo, m.LocatNo }).ToList(); if (detailGroup.Count > 1) { throw new Exception($"未在库内查询到该托盘信息"); } #region 集合 Db.BeginTran(); try { // 储位号 var de = stockDetailList.First(); var locateNo = de.LocatNo; #region 判断 //判断托盘是否在库内 if (string.IsNullOrWhiteSpace(locateNo)) { if (de.WareHouseNo == "W02")//盘断是否是零箱库 { if (de.SkuNo == "100099")//判断是否是空托出库 { //判断总库存是否为0,如果为0删除 否则减去数量 var stock = Db.Queryable().First(m => m.SkuNo == "100099"); if (stock != null) { if (de.Qty != null) { stock.Qty -= de.Qty.Value; Db.Updateable(stock).ExecuteCommand(); } if (stock.Qty == 0) { Db.Deleteable(stock).ExecuteCommand(); } } //托盘状态改为未使用 var sCode = Db.Queryable().First(m => m.PalletNo == de.PalletNo); if (sCode != null) { sCode.Status = "0"; Db.Updateable(sCode).ExecuteCommand(); } foreach (var item in stockDetailList) { Db.Deleteable(item).ExecuteCommand(); } str = "出库完成"; return outDtoList; } foreach (var item in stockDetailList) { item.LocatNo = "";//储位更改(改为空) item.WareHouseNo = "";//所属仓库更改(改为空) item.RoadwayNo = "";//所属巷道更改(改为空) item.AreaNo = "";//所属区域更改(改为空) Db.Updateable(de).ExecuteCommand(); } str = "出库完成"; return outDtoList; } } var locate = Db.Queryable().First(m => m.LocatNo == locateNo && m.IsDel == "0");//当前出库的储位信息 if (locate == null) { throw new Exception($"出库的托盘储位信息错误、在储位表中未查询到"); } //判断储位标志是否为损坏 if (locate.Flag == "2") { throw new Exception($"当前托盘所在的储位已损坏,不能出库,请核实"); } if (locate.Status != "1") { throw new Exception($"当前托盘所在的储位状态不是有物品,不能出库,请核实"); } #endregion #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 = outMode,//目标位置 PalletNo = de.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 + "到" + outMode + "的出库任务", //关键信息 }; Db.Insertable(exTask).ExecuteCommand(); outDtoList.Add(new OutCommandDto() { PalletNo = palletNo,//托盘号 StartLocate = locate.LocatNo, // 起始位置 StartRoadway = locate.RoadwayNo, EndLocate = outMode, // 目标位置 TaskNo = exTask.TaskNo, // 任务号 TaskType = "1",// 任务类型 (出库) OutMode = outMode, //目标地址 Order = 1 }); #endregion #region 改变数据 //判断是否为空托盘 if (de.SkuNo == "100099") { //增加锁定数量 de.LockQty += de.Qty; //增加锁定数量 de.Status = "2"; //状态 2:已分配 stocka.LockQty += (int)de.Qty; //增加库存总量锁定数量 Db.Updateable(de).ExecuteCommand(); Db.Updateable(stocka).ExecuteCommand(); } locate.Status = "3"; //要出库的储位改变状态 正在出库 Db.Updateable(locate).ExecuteCommand(); #endregion //添加操作日志记录 new OperationSOServer().AddLogOperationSo("出库作业", "托盘出库", palletNo, "出库", $"点击出库按钮出库托盘为:{palletNo}", userId); Db.CommitTran(); if (outDtoList.Count > 0) { // 正式运行程序放开 var list2 = outDtoList.Select(m => m.TaskNo).ToList(); var jsonData = JsonConvert.SerializeObject(outDtoList); 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 outDtoList; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } #endregion } catch (Exception e) { throw new Exception(e.Message); } } #endregion #region 自动分配、取消分配、获取手动分配的数据源、手动分配 // 判断是否是跨批出库 public bool IsCrossLotNo(string soNo) { try { //方法返回结果:bl var bl = true; //查询单据信息 var notice = Db.Queryable().First(m => m.SONo == soNo && m.IsDel == "0"); //判断单据类型 成品出库、领料出库(其它类型跳出此方法) if (notice.Type != "0" && notice.Type != "1") { return bl; } //查询到当前单据下的出库单明细信息 var noticeDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == soNo).ToList(); //库存总表信息 var data = Db.Queryable().Where(m => m.IsDel == "0").ToList(); //库存明细中检验合格批次集合 var dataDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.InspectStatus == "1").GroupBy(g => g.LotNo).Select(s => s.LotNo).ToList(); //库存明细表信息 var dataBoxInfo = Db.Queryable().Where(m => m.IsDel == "0").ToList(); //循环单据明细信息 foreach (var item in noticeDetail) { //验证先进先出原则 //获取当前物料的所有批次信息(排除单据的批次,防止单据所在批次锁定数量后验证小于等于0) var forData = data.Where(m => m.SkuNo == item.SkuNo && m.LotNo != item.LotNo && (m.Qty - m.FrozenQty - m.LockQty) > 0 && dataDetail.Contains(m.LotNo)).Select(m => m.LotNo).ToList(); forData.Add(item.LotNo); //集合添加单据的批次 //获取排序后的第一个批次 var firstLotNo = forData.OrderBy(m => m).First(); if (firstLotNo != item.LotNo) { bl = false; break; } //验证效期优先原则 var forDataBox = dataBoxInfo.Where(m => m.SkuNo == item.SkuNo && m.LotNo != item.LotNo && m.Qty > 0).ToList(); //获取当前单据批次的最近效期 var expirationTimedt = dataBoxInfo.Where(m => m.SkuNo == item.SkuNo && m.LotNo == item.LotNo && m.Qty > 0).ToList(); if (expirationTimedt.Count > 0) { var expirationTime = expirationTimedt.OrderBy(m => m.ExpirationTime).Select(m => m.ExpirationTime).First(); //获取库存中其它批次效期大于当前单据批次的效期数量 var num = forDataBox.Count(m => m.ExpirationTime > expirationTime); //判断是否大于0 if (num > 0) { bl = false; break; } } else { var dataDetailtime = Db.Queryable().Where(m => m.IsDel == "0" && m.InspectStatus == "1"). Where(m => m.SkuNo == item.SkuNo && m.LotNo == item.LotNo && m.Qty > 0) .OrderBy(m => m.ExpirationTime) .Select(m => m.ExpirationTime).First(); var num = forDataBox.Count(m => m.ExpirationTime > dataDetailtime); //判断是否大于0 if (num > 0) { bl = false; break; } } } return bl; } catch (Exception e) { throw new Exception(e.Message); } } /// /// 自动分配 /// /// /// /// /// public bool AutoAllot(string soNo, int userId) { try { #region 判断条件(出库单、出库单明细) //出库单 var notice = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == soNo).ToList().FirstOrDefault(); if (notice == null) { throw new Exception("未查询到出库单据信息"); } if (notice.Status != "0" && notice.Status != "1") { throw new Exception("参数异常,请检查状态是否为等待执行或部分分配;"); } //出库单明细 var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == soNo && (m.AllotQty - m.Qty) <= 0).ToList(); if (!detailList.Any()) { throw new Exception("未查询到符合分配条件的出库单据明细信息"); } #endregion var exAllotList = new List(); var assign = new AllotSku(); Db.BeginTran(); try { List soDetailList = new List(); foreach (var detail in detailList) { if (detail.AllotQty >= detail.Qty) { continue; } //还需要分配的数量 decimal needQty = detail.Qty - (detail.AllotQty == null ? 0 : decimal.Parse(detail.AllotQty.ToString())); //库存明细 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)) { 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("库存不足,无可出库库存"); } //0:成品出库、1:领料出库、2:抽检出库、4:不合格品出库、7:其他出库、9:生产领料出库 ///3:取样出库、5:中间品出库、8:寄存出库 if (notice.Type == "0" || notice.Type == "1" || notice.Type == "9")//成品、领料出库 { stockDetail = stockDetail.Where(m => m.InspectStatus == "1").ToList(); } else if (notice.Type == "2")//抽检出库 { stockDetail = stockDetail.Where(m => m.InspectStatus == "0" || m.InspectStatus == "1" || m.InspectStatus == "2").ToList(); } else if (notice.Type == "4")//不合格出库 { stockDetail = stockDetail.Where(m => m.InspectStatus == "2").ToList(); } else if (notice.Type == "7") //、其它 { stockDetail = stockDetail.Where(m => m.InspectStatus == "0" || m.InspectStatus == "1").ToList(); } if (stockDetail.Sum(m => m.Qty - m.LockQty) < needQty) { throw new Exception("库存明细数量不足"); } #region 包装信息 var pNum = 0;//托盘物品数量 var bNum = 0;//箱物品数量 //公共方法获取包装数量 new Common().GetPackQtyInfo(detail.PackagNo, ref pNum, ref bNum); #endregion //取合适库存商品 Dictionary stockQtyDic = new Dictionary();//托出库物品数 var qty = 0m; var house = ""; //分配货物 qty += assign.AllotPallets(stockDetail, needQty, pNum, bNum, stockQtyDic, notice.WareHouseNo); foreach (var sc in stockQtyDic) { var s = stockDetail.FirstOrDefault(m => m.Id == sc.Key); //添加分配表信息 var allot = new BllExportAllot { SONo = notice.SONo, 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(); } detail.AllotQty += qty; detail.UpdateUser = userId; detail.UpdateTime = DateTime.Now; if (detail.Status == "0") { detail.Status = "1"; } if (qty > detail.Qty) { //库存总表 var stock = Db.Queryable().First(d => d.IsDel == "0" && d.SkuNo == detail.SkuNo && d.LotNo == detail.LotNo); stock.LockQty += qty - detail.Qty; Db.Updateable(stock).ExecuteCommand(); //添加回传上游系统锁定数量更改代码 SoDetailInfo soDetail = new SoDetailInfo(); soDetail.OrderDetailCode = detail.OrderDetailCode; soDetail.LockQty = qty - detail.Qty; soDetail.LotNo = detail.LotNo; soDetailList.Add(soDetail); } } 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(); //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "分配", $"自动分配了单据号为{notice.SONo}的单据信息", userId); if (zd > 0 && mx > 0 && fp > 0 && k) { #region 通过接口发送至erp //系统对接后放开 /*var jsonData = JsonConvert.SerializeObject(soDetailList); var response = HttpHelper.DoPost(url, jsonData, "库存锁定数量变更", "ERP"); var obj = JsonConvert.DeserializeObject(response);//解析返回数据 if (obj.Success != 0) { throw new Exception("上传失败" + obj.Message); }*/ #endregion Db.CommitTran(); return true; } Db.RollbackTran(); return false; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } catch (Exception e) { throw new Exception("自动分配失败:" + e.Message); } } //取消分配 public bool CancelAllot(string soNo, int userId) { try { var notice = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == soNo).ToList().FirstOrDefault(); if (notice == null) { throw new Exception("未查询到出库单据信息"); } if (notice.Status != "1" && notice.Status != "2") { throw new Exception("参数异常,请检查状态是否为已分配或部分分配或来源是否是WMS"); } //该单据的分配信息 Status 0:任务下发 1:待拣货 2:部分拣货 3:待回库 4:已完成 var allotList = Db.Queryable().Where(o => o.IsDel == "0" && o.SONo == soNo).ToList(); //有已执行的分配数据不能取消 if (allotList.Any(o => o.Status != "0")) { throw new Exception("当前单据的分配信息已有执行中,不能取消分配"); } List soDetailList = new List(); //开启事务 Db.BeginTran(); try { //查询分配的明细 var detail = Db.Queryable().Where(d => d.SONo == soNo && d.AllotQty > 0 && d.IsDel == "0").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(); if (d.AllotQty > d.Qty) { //库存总表 var stock = Db.Queryable().First(m => m.IsDel == "0" && m.SkuNo == d.SkuNo && m.LotNo == d.LotNo); stock.LockQty -= (decimal)d.AllotQty - d.Qty; Db.Updateable(stock).ExecuteCommand(); //添加回传上游系统锁定数量更改代码 SoDetailInfo soDetail = new SoDetailInfo(); soDetail.OrderDetailCode = d.OrderDetailCode; soDetail.LockQty = (decimal)(d.Qty - d.AllotQty); soDetail.LotNo = d.LotNo; soDetailList.Add(soDetail); } 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 = ""; // } //} } //查询当前单据是否已添加备料任务 if (notice.Type == "1") { var task = Db.Queryable().First(m => m.IsDel == "0" && m.SoNo == soNo); if (task != null) { task.IsDel = "1"; task.UpdateUser = userId; task.UpdateTime = DateTime.Now; Db.Updateable(task).ExecuteCommand(); } } notice.Status = "0"; notice.UpdateUser = userId; notice.UpdateTime = DateTime.Now; Db.Updateable(detail).ExecuteCommand(); Db.Updateable(notice).ExecuteCommand(); //系统对接后放开 /*var jsonData = JsonConvert.SerializeObject(soDetailList); var response = HttpHelper.DoPost(url, jsonData, "库存锁定数量变更", "ERP"); var obj = JsonConvert.DeserializeObject(response);//解析返回数据 if (obj.Success != 0) { throw new Exception("上传失败" + obj.Message); }*/ //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "取消分配", $"取消分配了单据号为{notice.SONo}的单据信息", userId); Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } return true; } catch (Exception e) { throw new Exception("取消分配失败" + e.Message); } } /// /// 维护出库单备注信息 /// /// /// /// public void EditNoticeDemo(int id, string demo, int userId) { try { var notice = Db.Queryable().First(m => m.IsDel == "0" && m.Id == id); if (notice == null) { throw new Exception("未查询到出库单据信息"); } notice.Demo = demo + "".Trim(); notice.UpdateUser = userId; notice.UpdateTime = DateTime.Now; int i = Db.Updateable(notice).ExecuteCommand(); if (i > 0) { //添加操作日志 new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "编辑", $"编辑了单据号为{notice.SONo}的备注信息", userId); } } catch (Exception ex) { throw new Exception(ex.Message); } } //获取库存明细信息(出库单手动分配选择数据源) public List GetHandOutList(int detailId, string houseNo, string roadwayNo, string locateNo, string msg, string palletNo) { try { var detail = Db.Queryable().First(d => d.Id == detailId); #region 判断条件 if (detail == null) { throw new Exception("获取失败,未找到指定出库单!"); } if (detail.Status != "0" && detail.Status != "1" && detail.AllotQty >= detail.Qty) { throw new Exception("获取失败,出库单状态不是等待执行或分配中!"); } if (detail.AllotQty >= detail.Qty) { throw new Exception("获取失败,出库单已分配完成!"); } var notice = Db.Queryable().First(a => a.SONo == detail.SONo); if (notice == null) { throw new Exception("获取失败,未找到指定出库单!"); } if (notice.Status == "3" && detail.AllotQty >= detail.Qty || notice.Status == "4" || notice.Status == "5") { throw new Exception("获取失败,出库单状态不允许!"); } #endregion Expression> item = Expressionable.Create() .AndIF(!string.IsNullOrWhiteSpace(houseNo), m => m.WareHouseNo == houseNo) .AndIF(!string.IsNullOrWhiteSpace(roadwayNo), m => m.RoadwayNo == roadwayNo) .AndIF(!string.IsNullOrWhiteSpace(locateNo), m => m.LocatNo == locateNo) .AndIF(!string.IsNullOrWhiteSpace(palletNo), m => m.PalletNo == palletNo) .AndIF(!string.IsNullOrWhiteSpace(msg), m => m.SkuNo.Contains(msg.Trim()) || m.SkuName.Contains(msg.Trim()) || m.LocatNo.Contains(msg.Trim())) .And(m => m.IsDel == "0" && m.SkuNo == detail.SkuNo && m.LotNo == detail.LotNo && (m.Status == "0" || m.Status == "1")) .ToExpression();//注意 这一句 不能少 var list = Db.Queryable().Where(item).Select(a => new StockDetailDto { Id = a.Id, SkuNo = a.SkuNo, SkuName = a.SkuName, Standard = a.Standard, LotNo = a.LotNo, LotText = a.LotText, SupplierLot = a.SupplierLot, Qty = a.Qty - a.LockQty - a.FrozenQty, LocatNo = a.LocatNo, RoadwayNo = a.RoadwayNo, PalletNo = a.PalletNo, Demo = a.Demo, }).ToList(); return list; } catch (Exception e) { throw new Exception(e.Message); } } //手动分配出库单明细 public void AddHandOutAllot(AddHandOutVm model, int userId) { try { #region 判断条件 //数据验证 var detail = Db.Queryable().First(a => a.IsDel == "0" && a.Id == model.Id); if (detail == null) { throw new Exception("操作失败,未找到指定出库单详情!"); } if (detail.AllotQty >= detail.Qty || (detail.Status != "0" && detail.Status != "1")) { throw new Exception("操作失败,出库单已分配完成!"); } var notice = Db.Queryable().First(a => a.IsDel == "0" && a.SONo == detail.SONo); if (notice == null) { throw new Exception("操作失败,未找到指定出库单!"); } if (notice.Status == "3" && detail.AllotQty >= detail.Qty || notice.Status == "4" || notice.Status == "5") { throw new Exception("操作失败,出库单已分配完成!"); } #endregion //单据明细需要的出库数量 var needQty = detail.Qty - detail.AllotQty; //分配的出库数量 var outQty = model.StockList.Select(s => s.Qty).ToList().Sum(); if (outQty != needQty) { throw new Exception("操作失败,出库数量与计划数量不一致!"); } var stockIds = model.StockList.Select(a => a.StockId).ToList(); //库存明细 var stockList = Db.Queryable().Where(a => stockIds.Contains(a.Id)).ToList(); //分配信息 var allots = Db.Queryable().Where(m => m.IsDel == "0" && m.SODetailNo == detail.Id && m.Status == "0").ToList(); //库存总表 //var stockz = Db.Queryable().First(d => d.IsDel == "0" && d.SkuNo == detail.SkuNo && d.LotNo == detail.LotNo); var allotList = new List(); decimal outQtys = 0; foreach (var st in model.StockList) { var stock = stockList.First(a => a.Id == st.StockId); if (stock == null) { throw new Exception("操作失败,部分储位库存异常!"); } if (st.Qty > (stock.Qty - stock.LockQty - stock.FrozenQty)) // 输入的数量 - 托盘上可用的数量(托盘上数量-锁定的数量-冻结的数量) { throw new Exception("操作失败,出库数量超出库存数量!"); } var bl = allots.FirstOrDefault(m => m.StockId == st.StockId); if (bl == null) { //添加分配表信息 var allot = new BllExportAllot { SONo = notice.SONo, WaveNo = "", SODetailNo = detail.Id, StockId = st.StockId, LotNo = stock.LotNo, LotText = stock.LotText, SupplierLot = stock.SupplierLot, SkuNo = stock.SkuNo, SkuName = stock.SkuName, Standard = stock.Standard, PalletNo = stock.PalletNo, IsBale = stock.IsBale, IsBelt = stock.IsBelt, Qty = st.Qty, CompleteQty = 0, Status = "0", LogisticsId = notice.LogisticsId, IsAdvance = "0", OutMode = "",//出库口 CreateUser = userId, CreateTime = DateTime.Now }; allotList.Add(allot); } else { bl.Qty += st.Qty; Db.Updateable(bl).ExecuteCommand(); } //库存明细 stock.LockQty += st.Qty; stock.Status = stock.LockQty == stock.Qty ? "2" : "1"; //库存总表 //stockz.LockQty += st.Qty; //Db.Updateable(stockz).ExecuteCommand(); Db.Updateable(stock).UpdateColumns(it => new { it.LockQty, it.Status }).ExecuteCommand(); outQtys += st.Qty; } Db.Insertable(allotList).ExecuteCommand(); //修改单据明细 detail.AllotQty += outQtys; detail.UpdateUser = userId; detail.UpdateTime = DateTime.Now; if (detail.Status == "0") { detail.Status = "1"; } Db.Updateable(detail).ExecuteCommand(); var detailList = Db.Queryable() .Where(m => m.IsDel == "0" && m.SONo == notice.SONo).ToList(); //修改出库单状态 if (notice.Status == "0" || notice.Status == "1") { decimal totalQty = 0; decimal totalAllotQty = 0; foreach (var item in detailList) { totalQty += item.Qty; totalAllotQty += Convert.ToInt32(item.AllotQty); } if (totalAllotQty >= totalQty) { notice.Status = "2";//证明分配数量大于等于出库数量 修改为已分配 } else if (totalAllotQty < totalQty && totalAllotQty > 0) { notice.Status = "1";//证明分配数量小于等于出库数量 修改为部分分配 } Db.Updateable(notice).ExecuteCommand(); } //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", notice.SONo, "分配", $"手动分配了单据号为{notice.SONo}、物料:{detail.SkuNo}、批次:{detail.LotNo}的单据信息", userId); Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } #endregion #region 下发出库、出库完成、重新下发任务、取消任务、异常处理 public string GetHouseBySo(string soNo) { try { var notcie = Db.Queryable().First(m=>m.IsDel == "0" && m.SONo == soNo); if (notcie == null) { throw new Exception("未查询到出库单信息"); } return notcie.WareHouseNo; } catch (Exception e) { throw new Exception(e.Message); } } public List IssueOutHouseLk(string soNo, string outMode, int userId, string url, out string str) { try { var outDto1 = new List(); //出库数据的集合(深度为1的储位) //记录错误信息的集合 //1:当前要出库的储位正在移出、2 出库的托盘储位信息错误(在储位表中未查询到)、3储位损坏不能出库、4 要出库的托盘正在入库 var flagList = new List(); var com = new Common(); var notice = Db.Queryable().First(m => m.SONo == soNo && m.IsDel == "0"); if (notice == null) { throw new Exception($"未找到{soNo}出库单信息"); } if (notice.WareHouseNo != "W02") { throw new Exception("仓库号错误"); } //所有要出库的出库分配信息(未下发的信息和待拣货的信息) var list = Db.Queryable().Where(a => a.IsDel == "0" && a.SONo == soNo && (a.Status == "0" || a.Status == "2")).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 = ""; // 储位号 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; } //判断是否是已经出过库又回库(状态为待拣货的) 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 (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).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 添加出库任务 var taskNo = new Common().GetMaxNo("TK"); var exTask = new LogTask //出库任务 { TaskNo = taskNo, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = locate.LocatNo,//起始位置 EndLocat = 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 + "到" + outMode + "的出库任务", //关键信息 }; Db.Insertable(exTask).ExecuteCommand(); logTaskList.Add(exTask); outDto1.Add(new OutCommandDto() { PalletNo = item.PalletNo,//托盘号 StartLocate = locate.LocatNo, // 起始位置 StartRoadway = locate.RoadwayNo,//其实巷道 EndLocate = outMode, // 目标位置 TaskNo = exTask.TaskNo, // 任务号 TaskType = "1",// 任务类型 (出库)0入 1出 2移 OutMode = outMode, //出库口 Order = 1, //UnstackingMode = "unstackingMode2",//拣货方式 0机器拆托出 1 人工拣货出 //CompleteQty = outCount2, //拆的件数 //BoxexQty = outCount, //总件数 }); taskNoStr = exTask.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(); } //var notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).ExecuteCommand(); } } } locate.Status = "3"; //要出库的储位改变状态 正在出库 Db.Updateable(locate).ExecuteCommand(); item.TaskNo = taskNoStr; // 出库分配信息中更新任务号 item.Status = "1"; // 出库分配信息状态改为正在执行 //item.UnstackingMode = unstackingMode2;//拆垛方式 item.OutMode = outMode;//出库口 //item.LoadingAddre = unstackingMode2 == "0" ? loadingAddre : "";//装车口 Db.Updateable(item).ExecuteCommand(); #endregion flagList.Add(0); } else if (locate.Status == "3") //出库中 { #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 notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).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 = item.OutMode;//出库口 //item.UnstackingMode = unstackingMode2;//拆垛模式 Db.Updateable(item).ExecuteCommand(); flagList.Add(0); #endregion } else if (locate.Status == "5") //移出中 { flagList.Add(1); } } //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", soNo, "出库", $"点击出库按钮出库单号为:{soNo}的出库单", 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 (flagList.Count(m => m == 5) > 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 List IssueOutHouseMk(string soNo, string outMode, 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(); var notice = Db.Queryable().First(m => m.SONo == soNo && m.IsDel == "0"); if (notice == null) { throw new Exception($"未找到{soNo}出库单信息"); } //所有要出库的出库分配信息(未下发的信息和待拣货的信息) var list = Db.Queryable().Where(a => a.IsDel == "0" && a.SONo == soNo && (a.Status == "0" || a.Status == "2")).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 locateListStrs = outStockDetail.Where(m=> !string.IsNullOrWhiteSpace(m.LocatNo)).Select(m => m.LocatNo).Distinct().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;//目标位置 // 储位号 var locateNo = outStockDetail.First(m => m.PalletNo == item.PalletNo).LocatNo; #region 判断托盘是否在库内 //判断托盘是否在库内 if (string.IsNullOrWhiteSpace(locateNo)) //库外 { if (notice.Type == "0") { flagList.Add(5); continue; } //判断托盘是否在入库中 var imBl = com.GetImTask(item.PalletNo); if (imBl != null) { flagList.Add(4); continue; } //判断是否是已经出过库又回库(状态为待拣货的 1) 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 (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).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") //有物品 { var row1 = int.Parse(locate.LocatNo.Substring(2,2)); var row2 = int.Parse(locate.AisleOne.Substring(2, 2)); //需要移库的信息 var NeedMoveInfo = IsNeedMoveLocate(locate, locateListStrs, out int isOut); if (isOut == 1) { //巷道组中有入库或移入的储位,或者是当前储位前有储位未下发成功的任务 flagList.Add(2); continue; } if (NeedMoveInfo.Count > 0)//需要移库 { //判断库内空储位是否够 var okRoad = Db.Queryable().Where(m => m.Status == "0" && m.IsDel == "0" && m.WareHouseNo == notice.WareHouseNo).Select(m => m.RoadwayNo).ToList(); var nullSlotNum = Db.Queryable().Count(m => m.RoadwayNo != locate.RoadwayNo && okRoad.Contains(m.RoadwayNo) && m.Status == "0"); //判断空储位的数量是否大于需要移库的数量 if (nullSlotNum >= NeedMoveInfo.Count) { var isYk = false; foreach (var s in NeedMoveInfo) { //储位列 var rows = int.Parse(s.Substring(2,2)); //获取移库储位 var moveAddress = GetMiJiMoveAddress(s, locate.AisleOne); var tary = Db.Queryable().First(m => m.LocatNo == s); if (string.IsNullOrWhiteSpace(moveAddress)) // 判断是否获取到移库的库位 { isYk = true; flagList.Add(5);//出库前有货物,需移库但未查询到空储位 break; //没有移库的库位了 } else { //判断托盘有没有回移的任务 //var hy = GetHyTask(item.ExportStockCode); //if (hy != null) //{ // var hyentity = dataContext.WmsExportTask.FirstOrDefault(m => m.TaskId == hy.TaskId); // if (hyentity != null) // { // isYk = true; // msgList.Add(6);//出库前有货物,需移库但是回移托盘 // break; //没有移库的库位了 // } //} var ykTaskNo = new Common().GetMaxNo("TK"); var ykTask = new LogTask //出库任务 { TaskNo = ykTaskNo, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = s,//起始位置 EndLocat = moveAddress,//outMode,//目标位置 PalletNo = tary.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "2",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = "从" + locate.LocatNo + "到" + toLocation + "的出库任务", //关键信息 }; Db.Insertable(ykTask).ExecuteCommand(); logTaskList.Add(ykTask); outDto1.Add(new OutCommandDto() { PalletNo = item.PalletNo,//托盘号 StartLocate = locate.LocatNo, // 起始位置 StartRoadway = locate.RoadwayNo,//其实巷道 EndLocate = toLocation,//outMode, // 目标位置 TaskNo = ykTaskNo, // 任务号 TaskType = "1",// 任务类型 (出库)0入 1出 2移 Order = Math.Abs(row2 - rows), }); var slotChange = Db.Queryable().First(m => m.LocatNo == s); var slotChange2 = Db.Queryable().First(m => m.LocatNo == moveAddress); slotChange.Status = "5"; //改变状态(正在出库) slotChange2.Status = "4"; // 改变状态(正在移入) Db.Updateable(slotChange).ExecuteCommand(); Db.Updateable(slotChange2).ExecuteCommand(); } } if (isYk) { break; } } else { flagList.Add(5); break; } } #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 = 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",// 任务类型 (出库)0入 1出 2移 OutMode = toLocation, //出库口 Order = Math.Abs(row2 - row1), }); taskNoStr = exTask.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(); } //var notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).ExecuteCommand(); } } } locate.Status = "3"; //要出库的储位改变状态 正在出库 Db.Updateable(locate).ExecuteCommand(); item.TaskNo = taskNoStr; // 出库分配信息中更新任务号 item.Status = "1"; // 出库分配信息状态改为正在执行 //item.UnstackingMode = unstackingMode2;//拆垛方式 item.OutMode = outMode;//出库口 //item.LoadingAddre = unstackingMode2 == "0" ? loadingAddre : "";//装车口 Db.Updateable(item).ExecuteCommand(); #endregion flagList.Add(0); } else if (locate.Status == "3") //出库中 { #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 notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).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 = item.OutMode;//出库口 //item.UnstackingMode = unstackingMode2;//拆垛模式 Db.Updateable(item).ExecuteCommand(); flagList.Add(0); #endregion } else if (locate.Status == "5") //移出中 { flagList.Add(1); } } outDto1.AddRange(moveDto); outDto1.AddRange(outDto2); //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", soNo, "出库", $"点击出库按钮出库单号为:{soNo}的出库单", 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 (flagList.Count(m => m == 5) > 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); } } /// /// 判断是否需要进行移库操作 /// /// 要出库的库位地址 /// 通道口 /// 要出口的储位集合 /// 是否出库 1:有未下发的任务在前面 /// 需要移库的集合(如果为空则不需移库) private List IsNeedMoveLocate(SysStorageLocat lcoate,List locateStrList, out int isOut) { var nowAddress = new List(); //需要移库的集合 // 010101 派列层 //var bol = String.CompareOrdinal(lcoate.LocatNo, lcoate.AisleOne); var sArray = lcoate.LocatNo.Substring(4,2); var row = int.Parse(sArray);//储位列 var sArray2 = lcoate.AisleOne.Substring(4, 2); var row2 = int.Parse(sArray2); //通道口列 isOut = 0; var bol = row2 - row > 0; //同组的储位集合 var slotList = Db.Queryable().Where(m => m.RoadwayNo == lcoate.RoadwayNo).ToList(); List list; if (bol) { //储位小于通道口 倒序 list = slotList.Where(m => m.Column < row2 && m.Column > row).Select(m => m.LocatNo).ToList(); } else { //储位大于通道口 正序 list = slotList.Where(m => m.Column > row2 && m.Column < row).Select(m => m.LocatNo).ToList(); } if (list.Any()) { //排除掉同巷道组中要出库的储位 if (locateStrList.Count != 0) { list = list.Where(m => !locateStrList.Contains(m)).ToList(); } //判断是否有入库中或正在移入的 var s = slotList.Where(m => list.Contains(m.LocatNo) && (m.Status == "2" || m.Status == "4")).Select(m => m.LocatNo).ToList(); if (s.Count > 0) { isOut = 1; return nowAddress; } //判断是否有在当前储位前未下发的任务(防止撞车) var w = Db.Queryable().Where(m => list.Contains(m.StartLocat) && m.IsSuccess == 0).Select(m => m.StartLocat).ToList(); if (w.Count > 0) { isOut = 1; return nowAddress; } if (bol) { //储位小于通道口 倒序 nowAddress = slotList.Where(m => list.Contains(m.LocatNo) && m.Status == "1").OrderByDescending(m => m.LocatNo).Select(m => m.LocatNo).ToList(); } else { //储位大于通道口 正序 nowAddress = slotList.Where(m => list.Contains(m.LocatNo) && m.Status == "1").OrderBy(m => m.LocatNo).Select(m => m.LocatNo).ToList(); } if (nowAddress.Count > 0) { return nowAddress; } } else { return nowAddress; } return nowAddress; } /// /// 获取移库目标库位 密集库 /// /// 需要移动的库位地址 /// 需要移动的库位的出口中转位 /// 出库单据或是波次单据 /// 中转口 /// 需回移的巷道id /// 需回移的巷道中转口 /// 目标库位地址 为"" 直接下发两次出库指令 public string GetMiJiMoveAddress(string oldAddress, string slotOut) { var newAddress = ""; //新库位 var newLaneWayAddress = ""; //新巷道口库位 // 获取移库目标储位 // var sArray = oldAddress.Substring(4,2); var ceng = int.Parse(sArray); // var sArray2 = slotOut.Substring(2, 2); var row2 = sArray2; //十字口 var shiKou = new List() { slotOut, "070501", "071301", "070502", "071302", }; var shiKou3 = new List(); foreach (var item in shiKou) { var a = item.Substring(4, 2); var b = item.Substring(2, 2); if (int.Parse(a) != ceng) continue; var s = Math.Abs(int.Parse(b) - int.Parse(row2)); if (shiKou3.Any(m => m.distNum == s)) continue; shiKou3.Add(new addreClass() { slotCode = item, distNum = s }); } //根据十字口差值最小的排序 shiKou3 = shiKou3.OrderBy(m => m.distNum).ToList(); /** //1 移动到最近的空储位,必须回移。 //根据四向车移动轨迹计算出最近空储位。 //出库完成后根据批次号 生产日期 出口计算回移储位。 //2 移动适合存放的组,系统自动计算是否回移。 //根据批次号 生产日期 出口 物料等计算出移库目标储位 //出库完成后,判断是否有比当前库位更合适的存储储位,有移动,无不移动。 */ var oldSlot = Db.Queryable().First(m => m.LocatNo == oldAddress); if (oldSlot == null) { throw new Exception("未能找到储位信息"); } #region 1不需要回移的 //后期库存托盘表改了后需要加筛选条件托盘的状态(退货/预拣) var tray1 = Db.Queryable().Where(m => m.LocatNo == oldAddress).ToList(); //根据物料、批次、托盘状态(退货/预拣/暂存等)分组判断 var d = tray1.GroupBy(m => new { m.SkuNo, m.LotNo, m.PalletTags }); var location = string.Empty; if (d.Any()) { //旧储位同组的储位集合 var slotList = Db.Queryable().Where(m => m.RoadwayNo == oldSlot.RoadwayNo).Select(m => m.LocatNo).ToList(); foreach (var item in d) { foreach (var item2 in item) { var okLan = Db.Queryable().Where(m => m.Status == "0" && m.IsDel == "0").Select(m => m.RoadwayNo).ToList(); var tray2 = Db.Queryable().Where(m => m.SkuNo == item2.SkuNo && m.LotNo == item2.LotNo && !slotList.Contains(m.LocatNo) && m.PalletTags == item2.PalletTags && okLan.Contains(m.RoadwayNo)).ToList(); foreach (var s in tray2) { if (string.IsNullOrWhiteSpace(s.RoadwayNo))//判断是否在库外,如是跳过 { continue; } var lan = Db.Queryable().Where(m => m.RoadwayNo == s.RoadwayNo).OrderBy(m => m.LocatNo).ToList(); //判断是否有入库中、出库中、移入中、移出中 if (lan.Count(m => m.Status == "2" || m.Status == "3" || m.Status == "4" || m.Status == "5") > 0) { continue; } if (lan.Count(m => m.Status == "0") > 0) { var bol = GetBecomingLocation(s.RoadwayNo, ref location); if (bol && !string.IsNullOrWhiteSpace(location)) { newAddress = location; return newAddress; } } } } } } #endregion #region 2需要回移的 ////如果没有找到合适的储位 //if (string.IsNullOrWhiteSpace(newAddress)) //{ // foreach (var s in shiKou3) // { // var r = int.Parse(s.slotCode.Substring(0, 2)); // var l = int.Parse(s.slotCode.Substring(2, 2)); // var c = int.Parse(s.slotCode.Substring(4, 2)); // //查询空储位 // var sqlString = $@"select LocatNo,Row,Column,Layer,(ABS(Row-{r}) + ABS(Column-{l}) ) as distNum // from SysStorageLocat where (AisleOneRow = {r} or AisleTwoRow = {r}) and Status in (0) and // RoadwayNo !='{oldSlot.RoadwayNo}' and RoadwayNo not in(select RoadwayNo from SysStorageRoadway where Status = 1) order by distNum,SlotCode"; // var addressModels = dataContext.ExecuteQuery(sqlString).ToList(); // foreach (var item in addressModels) // { 、 // newAddress = item.slotCode; // var dz = newAddress.Split(new char[] { '-' }); // var l1 = dz[1]; // var c1 = dz[0]; // newLaneWayAddress = $"{c1}-{l1}-{a[2]}"; // flags = newLaneWayAddress; // var slotModel = dataContext.WmsBaseSlot.FirstOrDefault(m => m.SlotCode == item.slotCode); // var lan = dataContext.WmsBaseSlot.Where(m => m.SlotLanewayId == slotModel.SlotLanewayId).ToList(); // if (slotModel.SlotRow > int.Parse(a[2])) // { // // 取最上面一排 // lan = lan.OrderBy(m => m.SlotCode).ToList(); // for (int i = 0; i < lan.Count; i++) // { // var slot = dataContext.WmsBaseSlot.FirstOrDefault(m => m.SlotCode == lan[i].SlotCode); // if (slot.SlotStatus == 0) // { // if (i == lan.Count - 1) // { // newAddress = lan[lan.Count - 1].SlotCode; // break; // } // else // { // continue; // } // } // else // { // newAddress = lan[i - 1].SlotCode; // break; // } // } // } // else // { // // 取最下面一排 // lan = lan.OrderByDescending(m => m.SlotCode).ToList(); // for (int i = 0; i < lan.Count; i++) // { // var slot = dataContext.WmsBaseSlot.FirstOrDefault(m => m.SlotCode == lan[i].SlotCode); // if (slot.SlotStatus == 0) // { // if (i == lan.Count - 1) // { // newAddress = lan[lan.Count - 1].SlotCode; // break; // } // else // { // continue; // } // } // else // { // newAddress = lan[i - 1].SlotCode; // break; // } // } // } // //添加回移任务 // AddHyTask(oldAddress, newAddress, newLaneWayAddress, oldSlot.SlotLanewayId, slotOut, billCode); // refLanWayId = slotModel.SlotLanewayId; // refLanOutCode = newLaneWayAddress; // //9:锁定储位 // var updateSlot = dataContext.WmsBaseSlot.Where(m => m.SlotLanewayId == slotModel.SlotLanewayId).ToList(); // var newAddressRow = dataContext.WmsBaseSlot.FirstOrDefault(m => m.SlotCode == newAddress); // if (newAddressRow.SlotRow > int.Parse(a[2])) // { // updateSlot = updateSlot.Where(m => m.SlotRow < newAddressRow.SlotRow && m.SlotRow > int.Parse(a[2])).OrderBy(m => m.SlotCode).ToList(); // } // else // { // updateSlot = updateSlot.Where(m => m.SlotRow > newAddressRow.SlotRow && m.SlotRow < int.Parse(a[2])).OrderByDescending(m => m.SlotCode).ToList(); // } // foreach (var source in updateSlot) // { // if (source.SlotCode == newAddress) // { // continue; // } // if (source.SlotStatus == 0) // { // source.SlotStatus = 8; // } // } // if (updateSlot.Count <= 0) // { // refLanWayId = ""; // refLanOutCode = ""; // } // dataContext.SubmitChanges(); // return newAddress; // } // } //} return newAddress; #endregion } /// /// 获取移库合适的储位 密集库 /// /// 合适组的巷道号 /// 分配储位 /// true:存在合适储位 False:不存在合适储位 private bool GetBecomingLocation(string laneWayId, ref string location) { bool bl = false; // 循环判断当前组是否有剩余储位 string sqlString = string.Empty; location = ""; // 判断储位组是否有空储位 关联库存明细表可防止储位状态不准确避免造成满入异常//not in ('1','2','4','6','7','8') sqlString = $"select LocatNo,Column,AisleOne from SysStorageLocat where RoadwayNo = {laneWayId} and Status in ('0') and LocatNo not in (select LocatNo from DataStockDetail where RoadwayNo = { laneWayId}) order by Row;"; var slotModel =Db.SqlQueryable(sqlString).ToList(); if (slotModel.Count == 0) { bl = false; } else // 存在空储位 { // 判断当前组合适的储位地址 var numstr = slotModel[0].AisleOne.Substring(4,2); int aisleRow = int.Parse(numstr); if (slotModel[0].Column > aisleRow) { // 取最上面一排 location = slotModel[0].LocatNo; } else { // 取最下面一排 location = slotModel[slotModel.Count - 1].LocatNo; } bl = true; } return bl; } private class addreClass { public string slotCode { get; set; } public int distNum { get; set; } } public class LocateInfo { public string LocatNo { get; set; } public int Column { get; set; } public string AisleOne { get; set; } } #endregion #endregion //------------------------------------------------------------------ #region 备料、备料出库 //生产备料定时任务 public void AddBeiLiaoTimer(string soNo, int userId) { try { var notice = Db.Queryable().First(m => m.SONo == soNo && m.IsDel == "0"); if (notice == null) { throw new Exception("未查询到出库单信息"); } var task = Db.Queryable().Count(m => m.SoNo == soNo); if (task>0) { throw new Exception("当前出库单已生成备料任务,无需重复点击"); } var exTask = new BllExportTimingTask() { SoNo = soNo, Status = 0, CreateUser = userId }; Db.Insertable(exTask).ExecuteCommand(); notice.Status = "3";//修改单据状态未正在执行 notice.UpdateTime = DateTime.Now; notice.UpdateUser = userId; Db.Updateable(notice).ExecuteCommand(); //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", soNo, "出库", $"点击备料按钮出库单号为:{soNo}的出库单", userId); } catch (Exception e) { throw new Exception(e.Message); } } // JC23 备料定时任务开始 领料单备料下发出库(调用wcs接口给他库位地址) public List BeiLiaoIssueOutHouse(string url) { try { var taskList = Db.Queryable().Where(m => m.IsDel == "0").ToList(); var taskList1 = taskList.Where(m => m.Status == 1).ToList(); if (taskList1.Count > 0) { return null; //单据备料出库一个一个下发,防止托盘前后挡着下发不成功 } var task = taskList.Where(m => m.Status == 0).OrderBy(m => m.Id).First(); if (taskList == null) { return null; //未查询到待备料出库的单据任务 } #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 notice = Db.Queryable().First(m => m.SONo == task.SoNo && m.IsDel == "0"); if (notice == null) { throw new Exception($"未找到{task.SoNo}出库单信息"); } //所有要出库的出库分配信息(未下发的信息和待拣货的信息) var list = Db.Queryable().Where(a => a.IsDel == "0" && a.SONo == task.SoNo && a.Status == "0").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 = "outMode";//目标位置 string unstackingMode2 = "1";//拆垛方式,0:机器人拆垛 1:PDA拆垛 // 储位号 var locateNo = outStockDetail.First(m => m.PalletNo == item.PalletNo).LocatNo; #region 判断 decimal boxexQty = 0;//托盘上总数量 //判断托盘是否在库内 if (string.IsNullOrWhiteSpace(locateNo)) { //判断托盘是否在入库中 var imBl = com.GetImTask(item.PalletNo); if (imBl != null) { flagList.Add(4); throw new Exception("要出库的托盘正在入库,等待入库完成后再出库"); } var de = outStockDetail.First(m => m.SkuNo == item.SkuNo && m.LotNo == item.LotNo && m.PalletNo == item.PalletNo); if (de != null && de.WareHouseNo == "W02")//平库备料区的过滤掉不下发 { item.Status = "1"; // 出库分配信息状态改为正在执行 item.OutMode = toLocation;//出库口 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 (notice.Status == "0" || notice.Status == "1" || notice.Status == "2") { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList(); if (detailList.Count(m => m.FactQty>0) > 0) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).ExecuteCommand(); } } flagList.Add(0); continue; } //判断是否是已经出过库又回库(状态为待拣货的 1) if (item.Status == "0") { //如果不在仓库内,当前分配信息直接更新出库完成 item.Status = "2";//状态 item.OutMode = toLocation;//出库口 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 (notice.Status == "0" || notice.Status == "1" || notice.Status == "2") { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList(); if (detailList.Count(m => m.FactQty>0) > 0) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).ExecuteCommand(); } } } flagList.Add(0); continue; } var locate = Db.Queryable().First(m => m.LocatNo == locateNo && m.IsDel == "0");//当前出库的储位信息 if (locate == null) { throw new Exception("出库的托盘储位信息错误(在储位表中未查询到)"); } //判断储位标志是否为损坏 if (locate.Flag == "2") { throw new Exception($"{locate.LocatNo}储位损坏不能出库"); } #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, //PalletType="0",//托盘类型 //UnstackingMode=unstackingMode,//拣货方式 //BoxexQty=boxexQty,//托盘上总数量 //CompleteQty= }); 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") //前面储位状态是入库中或者移入中 { throw new Exception($"当前要出库的储位前{slotBefore.LocatNo}储位正在入库或移入"); } #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 (notice.Status == "0" || notice.Status == "1" || notice.Status == "2") { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList(); if (detailList.Count(m => m.FactQty > 0) > 0) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).ExecuteCommand(); } } } locate.Status = "3"; //要出库的储位改变状态 正在出库 Db.Updateable(locate).ExecuteCommand(); item.TaskNo = taskNoStr; // 出库分配信息中更新任务号 item.Status = "1"; // 出库分配信息状态改为正在执行 item.UnstackingMode = unstackingMode2;//拆垛方式 item.OutMode = toLocation;//出库口 //item.LoadingAddre = "";//装车口 Db.Updateable(item).ExecuteCommand(); #endregion flagList.Add(0); } else if (locate.Status == "3") //出库中 { #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 notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice.Status == "0" || notice.Status == "1" || notice.Status == "2") { var detailList = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList(); if (detailList.Count(m => m.FactQty > 0) > 0) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).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 = item.OutMode;//出库口 //item.LoadingAddre = unstackingMode2 == "0" ? taskNo.EndLocat : "";//装车口 Db.Updateable(item).ExecuteCommand(); flagList.Add(0); #endregion } else if (locate.Status == "5") //移出中 { throw new Exception($"当前要出库的储位{locate.LocatNo}正在移出"); } } outDto1.AddRange(moveDto); outDto1.AddRange(outDto2); ////添加操作日志记录 //var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", task.SoNo, "出库", $"点击出库按钮出库单号为:{task.SoNo}的出库单", userId); Db.CommitTran(); 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); //} //修改定时任务表 task.Status = 1; task.UpdateTime = DateTime.Now; Db.Updateable(task).ExecuteCommand(); } 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); } } //JC23 生产叫料定时任务开时 public List ProCallIssueOutHouse(string url) { try { //先查询任务表中要有任务的投料口信息 var proCallList = Db.Queryable().Where(m => m.IsDel == "0").ToList(); var proLocationList = proCallList.Select(m=>m.PutInLocation).ToList(); if (proCallList.Count == 0) { return null; } //获取任务中涉及到的投料口包含的工位集合 var locate = Db.Queryable().Where(m => m.IsDel == "0" && proLocationList.Contains(m.AreaNo)).ToList(); var outlist = new List(); //判断任务表中是否有未下发成功的,如果有重新下发 foreach (var item in proLocationList) { //当前投料口包含的工位 var list = locate.Where(m => m.AreaNo == item).ToList(); var listStr = locate.Where(m => m.AreaNo == item).Select(m=>m.LocatNo).ToList(); //判断投料口的工位中是否有未下发成功的任务 var task = Db.Queryable().Where(m => m.Type == "1" && m.IsSuccess == 0 && m.Status == "0" && listStr.Contains(m.EndLocat) ).OrderBy(m=>m.TaskNo).ToList(); if(task.Count > 0) { foreach (var item2 in task) { //添加下发任务的信息 var outInfo = new OutCommandDto() { PalletNo = item2.PalletNo,//托盘号 StartLocate = item2.StartLocat, // 起始位置 StartRoadway = item2.StartRoadway,//起始巷道 EndLocate = item2.EndLocat,//outMode, // 目标位置 TaskNo = item2.TaskNo, // 任务号 TaskType = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1, }; outlist.Add(outInfo); //item2.IsSuccess = 1; //item2.Status = "1"; //Db.Updateable(item2).ExecuteCommand(); } //return outlist; } } if (outlist.Count>0) { //将任务发送至AGV // 正式运行程序放开 var list2 = outlist.Select(m => m.TaskNo).ToList(); var jsonData = JsonConvert.SerializeObject(outlist); string response = ""; try { var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss") //response = HttpHelper.DoPost(url, jsonData, "下发给AGV叫料出库命令", "AGV"); 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); //} //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 null; } catch (Exception e) { throw new Exception(e.Message); } } //agv返回的成功信号(出库成功) public void ExportSuccessAGV(string taskNo, int userId) { try { //当前任务信息 var task = Db.Queryable().First(m => m.TaskNo == taskNo && m.IsDel == "0"); if (task == null) { throw new Exception($"未查询到任务号为:‘{taskNo}’的任务信息"); } if (task.Status == "2") { throw new Exception("当前任务已完成"); } Db.BeginTran(); //库存中当前托盘的信息 var stockDetail = Db.Queryable().Where(m => m.PalletNo == task.PalletNo).ToList(); var locateNo = stockDetail.Select(m => m.LocatNo).Distinct().FirstOrDefault(); //当前任务中的储位信息 var locate = Db.Queryable().First(m => m.LocatNo == task.StartLocat); var locate2 = Db.Queryable().First(m => m.LocatNo == task.EndLocat); try { task.Status = "2";//任务状态 task.IsSend = 0; task.IsCancel = 0; task.IsFinish = 0; task.FinishDate = DateTime.Now;//完成时间 Db.Updateable(task).ExecuteCommand(); if (locate != null) { locate.Status = "0"; // 更改当前任务中的储位状态(改为0空储位) Db.Updateable(locate).ExecuteCommand(); } if (locate2 != null) { locate2.Status = "1"; // 更改当前任务中的储位状态(改为1有物品) Db.Updateable(locate2).ExecuteCommand(); } #region 添加下一条叫料任务 var list = new List() { "B02" }; if (task.EndLocat == "空托盘收集器储位" && list.Contains(task.StartRoadway)) { var exTime = Db.Queryable().First(m => m.IsDel == "0" && m.PutInLocation == locate.AreaNo && m.SkuNo == locate.SkuNo); if (exTime != null) { var notice = Db.Queryable().First(m=>m.IsDel =="0" && m.SONo == exTime.OrderCode); //获取备好料的托盘信息 var taskStr = Db.Queryable().Where(m => m.IsDel == "0" && (m.Status == "0" || m.Status == "1") && m.Receiver == "AGV").Select(m => m.TaskNo).ToList(); var allotList = Db.Queryable().Where(m => m.IsDel == "0" && m.Status == "2" && m.SONo == notice.SONo && m.SkuNo == locate.SkuNo && !taskStr.Contains(m.TaskNo)).Select(m => m.PalletNo).ToList(); if (allotList.Count >0) { var stockDetail2 = Db.Queryable().Where(m => allotList.Contains(m.PalletNo)).OrderBy(m => m.LocatNo).First(); //出库任务 var exTask = new LogTask { TaskNo = new Common().GetMaxNo("TK"), Sender = "WMS", Receiver = "AGV", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = stockDetail2.LocatNo,//起始位置 EndLocat = task.StartLocat,//目标位置 PalletNo = stockDetail2.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = "从" + stockDetail2.LocatNo + "到" + task.StartLocat + "的出库任务", //关键信息 FinishIsPick = "1" }; Db.Insertable(exTask).ExecuteCommand(); //更改状态及信息 var locateStart = Db.Queryable().First(m => m.LocatNo == stockDetail2.LocatNo); locateStart.Status = "5"; Db.Updateable(locateStart).ExecuteCommand(); var locateEnd = Db.Queryable().First(m => m.LocatNo == task.StartLocat); locateEnd.Status = "4"; locateEnd.SkuNo = stockDetail2.SkuNo; locateEnd.PalletNo = stockDetail2.PalletNo; Db.Updateable(locateStart).ExecuteCommand(); } else { var listLocate = Db.Queryable().Where(m => m.IsDel == "0" && m.AreaNo == locate.AreaNo).ToList(); if (listLocate.Count(m=>m.SkuNo == locate.SkuNo && m.Status != "0") == 0) { Db.Deleteable(exTime).ExecuteCommand(); } locate.SkuNo = ""; // 更改当前任务中的物料记录(改为空) locate.PalletNo = ""; Db.Updateable(locate).ExecuteCommand(); } } Db.CommitTran(); return; } #endregion foreach (var item in stockDetail) { if (task.FinishIsPick == "1") { //出库流水(更改状态) var allot = Db.Queryable().First(m => m.IsDel == "0" && (m.TaskNo == taskNo || (m.Status == "2" && m.PalletNo == task.PalletNo))); #region 拣货信息 var stockInfoList = Db.Queryable().Where(m => m.IsDel == "0" && m.StockDetailId == item.Id).ToList(); var pickQty = 0m;//拣货的数量 var comList = new List(); foreach (var item2 in stockInfoList) { //添加拣货明细 var completeDetail = new BllCompleteDetail() { SONo = allot.SONo, SODetailNo = allot.SODetailNo, ExportAllotId = allot.Id, StockId = item.Id, BoxNo = item2.BoxNo, BoxNo2 = item2.BoxNo2, BoxNo3 = item2.BoxNo3, LotNo = item2.LotNo, LotText = item2.LotText, SupplierLot = item2.SupplierLot, SkuNo = item2.SkuNo, SkuName = item2.SkuName, Standard = item2.Standard, PalletNo = item2.PalletNo, CompleteQty = item.Qty, CreateUser = userId }; comList.Add(completeDetail); pickQty += item2.Qty; //删除库存箱码明细 Db.Deleteable(item2).ExecuteCommand(); } if (comList.Count>0) { Db.Insertable(comList).ExecuteCommand(); } #endregion #region 更改库存总表数据 //更改库存总表数据 var stock = Db.Queryable().First(m => m.SkuNo == item.SkuNo && m.LotNo == item.LotNo); if (stock != null) { if (item.LockQty != null) { stock.Qty -= item.LockQty.Value; stock.LockQty -= item.LockQty.Value; Db.Updateable(stock).ExecuteCommand(); } if (stock.Qty == 0) { Db.Deleteable(stock).ExecuteCommand(); } } #endregion #region 出库流水(更改状态) allot.Status = "5"; if (stockInfoList.Count == 0) { allot.CompleteQty += item.LockQty; } else { allot.CompleteQty += pickQty; } Db.Updateable(allot).ExecuteCommand(); #endregion #region 出库单及明细 var noticeDetail = Db.Queryable().First(m => m.Id == allot.SODetailNo && m.IsDel == "0"); if (stockInfoList.Count == 0) { noticeDetail.CompleteQty += item.LockQty; } else { noticeDetail.CompleteQty += pickQty; } Db.Updateable(noticeDetail).ExecuteCommand(); var num = Db.Queryable().Count(m => m.IsDel == "0" && m.SONo == allot.SONo && m.CompleteQty < m.Qty); if (num <= 0) { var notice = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == noticeDetail.SONo); notice.Status = "4"; //更改为执行完成//修改出库单信息 Db.Updateable(notice).ExecuteCommand(); } #endregion Db.Deleteable(item).ExecuteCommand(); continue; } if (task.StartLocat == "outMode") { var count = Db.Queryable().Where(m => m.IsDel == "0" && m.Status != "2" && m.SONo == item.SONo && m.TaskNo != taskNo).Count(); if (count == 0) { var exportTimingTask = Db.Queryable().First(m => m.SoNo == item.SONo && m.IsDel == "0"); if (exportTimingTask != null) { exportTimingTask.Status = 2; exportTimingTask.UpdateTime = DateTime.Now; Db.Updateable(exportTimingTask).ExecuteCommand();//删除定时任务; } } } item.LocatNo = locate2.LocatNo;//储位更改(改为空) item.WareHouseNo = locate2.WareHouseNo;//所属仓库更改(改为空) item.RoadwayNo = locate2.RoadwayNo;//所属巷道更改(改为空) item.AreaNo = locate2.AreaNo;//所属区域更改(改为空) Db.Updateable(item).ExecuteCommand(); } if (userId != 0) { //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库日志", taskNo, "完成", $"点击完成按钮、完成任务号为:{taskNo}的任务", userId); } Db.CommitTran(); } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } catch (Exception ex) { throw new Exception("完成反馈失败:" + ex.Message); } } #endregion #region 下发出库、出库完成、重新下发任务、取消任务、异常处理 // 下发出库(调用cs接口给他库位地址) public List IssueOutHouse(string soNo, 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 notice = Db.Queryable().First(m => m.SONo == soNo && m.IsDel == "0"); if (notice == null) { throw new Exception($"未找到{soNo}出库单信息"); } //所有要出库的出库分配信息(未下发的信息和待拣货的信息) var list = Db.Queryable().Where(a => a.IsDel == "0" && a.SONo == soNo && (a.Status == "0" || a.Status == "2")).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拆垛 decimal? outCount = 0; decimal? outCount2 = 0; #region 判断是否需要拆箱 if (notice.Type == "0")//成品出库 { 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 = outMode;//装车口 var zongNum = outStockDetail.First(m => m.Id == item.StockId).Qty; outCount = zongNum / (decimal)packagInfo.L2Num; //托盘总件数 outCount2 = item.Qty / (decimal)packagInfo.L2Num; //要拣货件数 } else //PDA拆垛 { toLocation = outMode;//出库口 } } else { unstackingMode2 = "1";//非成品出库走PDA拆垛 toLocation = outMode;//出库口 } #endregion // 储位号 var locateNo = outStockDetail.First(m => m.PalletNo == item.PalletNo).LocatNo; #region 判断 decimal boxexQty = 0;//托盘上总数量 //判断托盘是否在库内 if (string.IsNullOrWhiteSpace(locateNo)) //库外 { if (notice.Type == "0") { flagList.Add(5); continue; } //判断托盘是否在入库中 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); 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 (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).ExecuteCommand(); } } flagList.Add(0); continue; } //判断是否是已经出过库又回库(状态为待拣货的 1) 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 (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).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",// 任务类型 (出库)0入 1出 2移 OutMode = toLocation, //出库口 Order = 1, UnstackingMode=unstackingMode2,//拣货方式 0机器拆托出 1 人工拣货出 CompleteQty= outCount2, //拆的件数 BoxexQty = outCount, //总件数 }); 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 = toLocation, //目标地址 Order = 1, UnstackingMode = "1",//拣货方式 0机器拆托出 1 人工拣货出 CompleteQty = 0, //拆的件数 BoxexQty = 0, //总件数 }); #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 = toLocation, //目标地址 Order = 1, UnstackingMode = unstackingMode2,//拣货方式 0机器拆托出 1 人工拣货出 CompleteQty = outCount2, //拆的件数 BoxexQty = outCount, //总件数 }); 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 (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).ExecuteCommand(); } } } locate.Status = "3"; //要出库的储位改变状态 正在出库 Db.Updateable(locate).ExecuteCommand(); item.TaskNo = taskNoStr; // 出库分配信息中更新任务号 item.Status = "1"; // 出库分配信息状态改为正在执行 item.UnstackingMode = unstackingMode2;//拆垛方式 item.OutMode = outMode ;//出库口 //item.LoadingAddre = unstackingMode2 == "0" ? loadingAddre : "";//装车口 Db.Updateable(item).ExecuteCommand(); #endregion flagList.Add(0); } else if (locate.Status == "3") //出库中 { #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 notice2 = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); if (notice.Status == "0" || notice.Status == "1" || notice.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) { notice.Status = "3"; //变更状态为正在执行 Db.Updateable(notice).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 = item.OutMode;//出库口 item.UnstackingMode = unstackingMode2 ;//拆垛模式 Db.Updateable(item).ExecuteCommand(); flagList.Add(0); #endregion } else if (locate.Status == "5") //移出中 { flagList.Add(1); } } outDto1.AddRange(moveDto); outDto1.AddRange(outDto2); //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", soNo, "出库", $"点击出库按钮出库单号为:{soNo}的出库单", 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 (flagList.Count(m => m == 5) > 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); } } //wcs返回的成功信号(出库成功) public void ExportSuccess(string taskNo, int userId) { try { //当前任务信息 var task = Db.Queryable().First(m => m.TaskNo == taskNo && m.IsDel == "0"); if (task == null) { throw new Exception($"未查询到任务号为:‘{taskNo}’的任务信息"); } if (task.Status == "2") { throw new Exception("当前任务已完成"); } Db.BeginTran(); //库存中当前托盘的信息 var stockDetail = Db.Queryable().Where(m => m.PalletNo == task.PalletNo).ToList(); var locateNo = stockDetail.Select(m => m.LocatNo).Distinct().FirstOrDefault(); //当前任务中的储位信息 var locate = Db.Queryable().First(m => m.LocatNo == locateNo); try { task.Status = "2";//任务状态 task.IsSend = 0; task.IsCancel = 0; task.IsFinish = 0; task.FinishDate = DateTime.Now;//完成时间 Db.Updateable(task).ExecuteCommand(); if (locate != null) { locate.Status = "0"; // 更改当前任务中的储位状态(改为0空储位) Db.Updateable(locate).ExecuteCommand(); } foreach (var item in stockDetail) { if (item.SkuNo == "100099")//判断是否是空托出库 { //判断总库存是否为0,如果为0删除 否则减去数量 var stock = Db.Queryable().First(m => m.SkuNo == "100099"); if (stock != null) { if (item.LockQty != null) { stock.Qty -= item.LockQty.Value; stock.LockQty -= item.LockQty.Value; Db.Updateable(stock).ExecuteCommand(); } if (stock.Qty == 0) { Db.Deleteable(stock).ExecuteCommand(); } } //托盘状态改为未使用 var sCode = Db.Queryable().First(m => m.PalletNo == item.PalletNo); if (sCode != null) { sCode.Status = "0"; Db.Updateable(sCode).ExecuteCommand(); } Db.Deleteable(item).ExecuteCommand(); #region 拣货信息 //var pickQty = 0;//拣货的数量 //var comList = new List(); // //添加拣货明细 // var completeDetail = new BllCompleteDetail() // { // SONo = "", // SODetailNo = 0, // ExportAllotId = 0, // StockId = exportAllot.StockId, // BoxNo = item.BoxNo, // BoxNo2 = item.BoxNo2, // BoxNo3 = item.BoxNo3, // LotNo = exportAllot.LotNo, // LotText = exportAllot.LotText, // SupplierLot = exportAllot.SupplierLot, // SkuNo = exportAllot.SkuNo, // SkuName = exportAllot.SkuName, // Standard = exportAllot.Standard, // PalletNo = palletNo, // CompleteQty = item.Qty, // CreateUser = userId // }; // comList.Add(completeDetail); // //删除库存箱码明细 // Db.Deleteable(item).ExecuteCommand(); // pickQty += item.Qty; // exportAllot.Status = "5"; //待回库 : 已完成 // exportAllot.CompleteQty += item.Qty; //拣货数量 // exportAllot.UpdateUser = userId; //修改人 // exportAllot.UpdateTime = serverTime; //修改时间 // Db.Updateable(exportAllot).ExecuteCommand(); // //验证拣货信息是否为已完成 // if (exportAllot.Status == "5") // { // break; // } //Db.Insertable(comList).ExecuteCommand(); #endregion continue; } item.LocatNo = "";//储位更改(改为空) item.WareHouseNo = "";//所属仓库更改(改为空) item.RoadwayNo = "";//所属巷道更改(改为空) item.AreaNo = "";//所属区域更改(改为空) Db.Updateable(item).ExecuteCommand(); } //出库流水(更改状态) var allot = Db.Queryable().Where(m => m.IsDel == "0" && (m.TaskNo == taskNo || (m.Status == "1" && m.PalletNo == task.PalletNo))).ToList(); var PalletType = "0"; //0:物料托 1:空托盘托 var soNo = ""; var sku = ""; foreach (var item in allot) { if (item.SkuNo == "100099") { item.Status = "5"; item.CompleteQty += stockDetail[0].Qty; PalletType = "1"; } else { item.Status = "2"; soNo = item.SONo; sku = item.SkuNo; } } //下发四楼调度AGV的任务 if ((task.EndLocat == "outMode" || task.EndLocat == "outMode") && PalletType == "0") { foreach (var item in allot) { var detail = Db.Queryable().First(m => m.Id == item.StockId); detail.SONo = item.SONo; Db.Updateable(detail).ExecuteCommand(); } var locatePing = new AllotLocation().GetPingLocate(soNo, sku); if (locatePing == null) { throw new Exception("平库未查询到空位置"); } var exTask = new LogTask //出库任务 { TaskNo = new Common().GetMaxNo("TK"), Sender = "WMS", Receiver = "AGV", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = task.EndLocat,//起始位置 EndLocat = locatePing.LocatNo,//outMode,//目标位置 PalletNo = task.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "1",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = "从" + task.EndLocat + "到" + locatePing.LocatNo + "的出库任务", //关键信息 }; Db.Insertable(exTask).ExecuteCommand(); var outDto = new List { new OutCommandDto() { PalletNo = task.PalletNo,//托盘号 StartLocate = task.EndLocat, // 起始位置 StartRoadway = "",//其实巷道 EndLocate = locatePing.LocatNo,//outMode, // 目标位置 TaskNo = exTask.TaskNo, // 任务号 TaskType = "1",// 任务类型 (出库)0入 1出 2移 OutMode = "", //出库口 Order = 1, //UnstackingMode = unstackingMode2,//拣货方式 0机器拆托出 1 人工拣货出 //CompleteQty = outCount2, //拆的件数 //BoxexQty = outCount, //总件数 } }; // 正式运行程序放开 var list2 = outDto.Select(m => m.TaskNo).ToList(); var jsonData = JsonConvert.SerializeObject(outDto); 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); //} //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); } } Db.Updateable(allot).ExecuteCommand(); if (userId != 0) { //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库日志", taskNo, "完成", $"点击完成按钮、完成任务号为:{taskNo}的任务", userId); } Db.CommitTran(); } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } catch (Exception ex) { throw new Exception("完成反馈失败:" + ex.Message); } } /// /// wcs返回的成功信号(移库成功) /// /// 任务号 /// 操作人 /// public void RelocationSuccess(string taskNo, int userId) { try { //当前任务信息 var task = Db.Queryable().First(m => m.TaskNo == taskNo && m.IsDel == "0"); if (task == null) { throw new Exception($"未查询到任务号为:‘{taskNo}’的任务信息"); } if (task.Status == "2") { throw new Exception("当前任务已完成"); } Db.BeginTran(); //库存中当前托盘的信息 var stockDetail = Db.Queryable().Where(m => m.PalletNo == task.PalletNo).ToList(); //当前任务中的目标储位信息 //当前任务中的原储位 var locate = Db.Queryable().First(m => m.LocatNo == task.StartLocat); if (locate == null) { throw new Exception($"WMS系统中没有该{task.StartLocat}储位对应的信息"); } var locate2 = Db.Queryable().First(m => m.LocatNo == task.EndLocat); if (locate2 == null) { throw new Exception($"WMS系统中没有该{task.EndLocat}储位对应的信息"); } try { task.Status = "2";//任务状态 task.IsSend = 0; task.IsCancel = 0; task.IsFinish = 0; task.FinishDate = DateTime.Now;//完成时间 Db.Updateable(task).ExecuteCommand(); #region 修改储位状态 //原储位改为空储位 0 locate.Status = "0"; Db.Updateable(locate).ExecuteCommand(); //目标储位改为有货物 1 locate2.Status = "1"; Db.Updateable(locate2).ExecuteCommand(); foreach (var item in stockDetail) { item.WareHouseNo = locate2.WareHouseNo; item.AreaNo = locate2.AreaNo; item.RoadwayNo = locate2.RoadwayNo; item.LocatNo = locate2.LocatNo; } Db.Updateable(stockDetail).ExecuteCommand(); #endregion Db.CommitTran(); } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } catch (Exception ex) { throw new Exception("完成反馈失败:" + ex.Message); } } //重新下发出库任务 public OutCommandDto AgainSendSoTask(string taskNo, int userId, string url) { try { var task = Db.Queryable().First(m => m.TaskNo == taskNo && m.IsDel == "0"); if (task == null) { throw new Exception("未查询到任务信息"); } var stockDetail = Db.Queryable().First(m => m.PalletNo == task.PalletNo); if (stockDetail == null) { throw new Exception(task.PalletNo + " 当前托盘未在库内,请核实信息"); } Db.BeginTran(); var locateNo = task.StartLocat; //判断任务中起始位置是否和库存中位置一致 if (task.StartLocat != stockDetail.LocatNo) { locateNo = stockDetail.LocatNo; task.StartLocat = locateNo; Db.Updateable(task).ExecuteCommand(); } var locate = Db.Queryable().First(m => m.LocatNo == locateNo); if (locate != null && locate.Status != "3") { locate.Status = "3"; Db.Updateable(locate).ExecuteCommand(); } var outDto = new OutCommandDto() { PalletNo = task.PalletNo,//托盘号 StartLocate = locateNo, // 起始位置 StartRoadway = locate.RoadwayNo, EndLocate = task.EndLocat, // 目标位置 TaskNo = task.TaskNo, // 任务号 TaskType = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1 }; //出库数据 //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库日志", taskNo, "下发", $"点击下发按钮、重新下发了任务号为:{taskNo}的任务", (int)userId); Db.CommitTran(); // 正式运行程序放开 var list = new List { outDto.TaskNo }; var jsonData = JsonConvert.SerializeObject(outDto); try { //程序正式发布后放开 var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss") var 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(list, time1, time2); } if (wcsModel.StatusCode == -1) { new TaskServer().EditTaskIssueNo(list, time1, time2, wcsModel.Msg); throw new Exception($"wcs返回状态异常:{wcsModel.Msg}"); } } catch (Exception ex) { throw new Exception(ex.Message); } return outDto; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } //取消出库任务 public void CancelSoTask(string taskNo, int userId) { try { Db.BeginTran(); try { var task = Db.Queryable().First(m => m.TaskNo == taskNo && m.IsDel == "0"); if (task == null) { throw new Exception("未查询到任务信息"); } //获取对应库位信息 var startlocat = Db.Queryable().First(a => a.IsDel == "0" && a.WareHouseNo == "W01" && a.LocatNo == task.StartLocat); if (startlocat == null) { throw new Exception("未查询到储位信息"); } startlocat.Status = "0";//修改分配信息状态 //获取储位信息 var locat = Db.Queryable().First(a => a.IsDel == "0" && a.WareHouseNo == "W01" && a.LocatNo == task.StartLocat); //获取移库任d务对应目标储位信息 SysStorageLocat endlocat = new SysStorageLocat(); if (task.Type == "2") { endlocat = Db.Queryable().First(a => a.IsDel == "0" && a.WareHouseNo == "W01" && a.LocatNo == task.EndLocat); if (endlocat == null) { throw new Exception("未查询到目标储位信息"); } } if (locat == null) { Db.RollbackTran(); throw new Exception("未查询到储位信息,请核实!"); } locat.Status = "1"; //有物品 Db.Updateable(locat).ExecuteCommand(); if (endlocat != null) { endlocat.Status = "0"; //空储位 0 Db.Updateable(endlocat).ExecuteCommand(); } //修改任务 task.IsSuccess = 1; task.IsSend = 0; task.IsCancel = 0; task.IsFinish = 0; task.Status = "4"; task.CancelDate = DateTime.Now; Db.Updateable(task).ExecuteCommand(); //出库分配信息 var allot = Db.Queryable().Where(m => m.IsDel == "0" && m.TaskNo == taskNo).ToList(); foreach (var item in allot) { item.Status = "0";//修改分配信息状态 item.TaskNo = ""; var noticeDetail = Db.Queryable().First(m => m.IsDel == "0" && m.Id == item.SODetailNo); if (noticeDetail == null) { throw new Exception("未查询到出库单明细信息"); } noticeDetail.FactQty -= item.Qty; //修改出库单明细的下架数量 Db.Updateable(noticeDetail).ExecuteCommand(); if (noticeDetail.FactQty == 0) { var noticeDetail2 = Db.Queryable().Where(m => m.IsDel == "0" && m.SONo == item.SONo && m.Id != noticeDetail.Id).ToList(); var num = noticeDetail2.Count(m => m.FactQty > 0); //判断出库单的所有明细是否都为0;如果为0变更出库单状态为已分配 if (num == 0) { var notice = Db.Queryable().First(m => m.IsDel == "0" && m.SONo == item.SONo); notice.Status = "2"; Db.Updateable(notice).ExecuteCommand(); } } } //判断是否存在分配信息 if (allot == null) { //获取库存明细 var stockDetail = Db.Queryable().First(a => a.IsDel == "0" && a.PalletNo == task.PalletNo); //获取库存 var datastock = Db.Queryable().First(a => a.IsDel == "0" && a.SkuNo == stockDetail.SkuNo); //获取储位信息 var locate = Db.Queryable().First(a => a.IsDel == "0" && a.WareHouseNo == "W01" && a.LocatNo == stockDetail.LocatNo); //判断是否为空托盘 if (stockDetail.SkuNo == "100099") { //修改库存明细 stockDetail.LockQty -= stockDetail.Qty; //锁定数量 stockDetail.Status = "0"; //库存状态 0:待分配 //修改库存总表 datastock.LockQty -= (int)stockDetail.Qty; //锁定数量 //修改储位状态 locate.Status = "1"; //储位状态 1:有物品 Db.Updateable(stockDetail).ExecuteCommand(); Db.Updateable(datastock).ExecuteCommand(); Db.Updateable(locate).ExecuteCommand(); } else { //修改储位状态 locate.Status = "1"; //储位状态 1:有物品 Db.Updateable(locate).ExecuteCommand(); } } else { Db.Updateable(allot).ExecuteCommand(); } //添加操作日志记录 var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库日志", taskNo, "取消", $"点击取消按钮、取消了任务号为:{taskNo}的任务", (int)userId); Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } catch (Exception e) { throw new Exception(e.Message); } } /// /// 空取异常 /// /// 任务反馈信息 /// public bool EmptyException(ReceiveWcsSignal model) { try { // 判断当前任务状态 Status 1:正在执行 3:异常结束 var taskModel = Db.Queryable().First(m => m.TaskNo == model.TaskNo && m.IsDel == "0" && m.Status == "1"); if (taskModel == null) { throw new Exception("此任务不存在或任务状态已变更!"); } Db.BeginTran(); // 将当前任务状态变更异常结束 taskModel.Status = "3"; taskModel.Information = "空取异常"; taskModel.IsSend = 0; taskModel.IsCancel = 0; taskModel.IsFinish = 0; taskModel.FinishDate = DateTime.Now; Db.Updateable(taskModel).ExecuteCommand(); // 改变当前储位地址的储位标志变更为屏蔽 var locatModel = Db.Queryable().First(m => m.LocatNo == taskModel.StartLocat && m.IsDel == "0"); locatModel.Flag = "1"; Db.Updateable(locatModel).ExecuteCommand(); var allotModels = Db.Queryable().Where(m => m.PalletNo == taskModel.PalletNo && (m.Status == "1" || m.Status == "0")).ToList(); // 循环处理应对同个托盘多个分配任务 foreach (BllExportAllot allotModel in allotModels) { // 出库明细表 状态修改为分配中 分配数量回滚 var noticeDetailModel = Db.Queryable().First(m => m.Id == allotModel.SODetailNo && m.IsDel == "0"); noticeDetailModel.AllotQty = noticeDetailModel.AllotQty - allotModel.Qty; if (allotModel.Status == "1") { noticeDetailModel.FactQty = noticeDetailModel.FactQty - allotModel.Qty; } noticeDetailModel.Status = "1"; Db.Updateable(noticeDetailModel).ExecuteCommand(); // 出库分配表 状态修改为异常取消 allotModel.Status = "6"; // 出库总表 状态改为部分分配 var noticeModel = Db.Queryable().First(m => m.SONo == noticeDetailModel.SONo && m.IsDel == "0"); noticeModel.Status = "1"; Db.Updateable(noticeModel).ExecuteCommand(); // 库存明细表 状态修改为异常锁定 锁定数量修改为托盘上数量 var stockDetailModel = Db.Queryable().First(m => m.Id == allotModel.StockId && m.IsDel == "0"); var lockQty = stockDetailModel.LockQty; stockDetailModel.Status = "5"; stockDetailModel.LockQty = stockDetailModel.Qty; Db.Updateable(stockDetailModel).ExecuteCommand(); // 库存总表 锁定数量=当前锁定数量 + (库存明细托盘上数量-库存明细托盘上已锁定的数量) var stockModel = Db.Queryable().First(m => m.LotNo == stockDetailModel.LotNo && m.SkuNo == stockDetailModel.SkuNo && m.IsDel == "0"); stockModel.LockQty = stockModel.LockQty + (int)(stockDetailModel.Qty - lockQty); Db.Updateable(stockModel).ExecuteCommand(); // 拣货明细表 删除 var completeDetailModels = Db.Queryable().Where(m => m.ExportAllotId == allotModel.Id && m.IsDel == "0").ToList(); Db.Deleteable(completeDetailModels).ExecuteCommand(); // 插入异常处理表 string exceptionNo = new Common().GetMaxNo("EX"); var exceptionModel = new SysException() { ExceptionNo = exceptionNo, Type = "0", PalletNo = taskModel.PalletNo, ExcLocatNo = taskModel.StartLocat, OrderNo = noticeModel.SONo, TaskNo = taskModel.TaskNo, Status = "0", Text = "", // 处理描述 CreateUser = 0 }; Db.Insertable(exceptionModel).ExecuteCommand(); } Db.Updateable(allotModels).ExecuteCommand(); Db.CommitTran(); return true; } catch (Exception e) { Db.RollbackTran(); throw new Exception("程序错误:" + e.Message); } } #endregion /// /// 判断出库是否需要拆箱 /// /// /// public string IsNeedUnpack(string soNo) { string result = "0";//是否需要拆箱,0:否 1:是 if (string.IsNullOrEmpty(soNo)) { throw new Exception("未找到对应出库单!"); } try { var notice = Db.Queryable().First(w => w.IsDel == "0" && w.SONo == soNo); if (notice == null) { throw new Exception("未找到对应出库单!"); } //物料编码表 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" && w.SONo == 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 GetArchivingExportNoticeList(string no, string type, string status, string lotNo, int? logisticsId, string isWave, string isDespatch, string waveNo, 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 ArchivingExportNotice AS tb1 "; sqlString += "SELECT DISTINCT tb1.Id,tb1.SONo,tb1.Type,tb1.Status,tb1.Origin,tb1.CustomerNo,tb1.CustomerName,tb1.LotNo, "; sqlString += "tb1.LotText,tb1.SupplierLot,tb1.LogisticsId,tb2.CarrierName as LogisticsName,tb1.IsWave,tb1.WaveNo,"; sqlString += "tb1.IsDespatch,tb1.Demo,tb3.RealName as CreateUserName,tb4.RealName as UpdateUserName,tb1.CreateTime,tb1.UpdateTime,"; sqlString += "tb5.RealName as CheckUserName,tb1.CheckTime "; sqlString += " FROM ArchivingExportNotice 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 += "LEFT JOIN SysUserInfor AS tb5 ON tb1.CheckUser = tb5.Id "; sqlPub += $"WHERE tb1.SONo LIKE '%{no}%' AND tb1.waveNo LIKE '%{waveNo}%' "; sqlPub += $"AND tb1.SoNo in " + $"(select DISTINCT SoNo from ArchivingExportNoticeDetail where isDel = '0' and lotNo like '%" + lotNo.Trim() + "%') "; if (!string.IsNullOrWhiteSpace(type)) { sqlPub += $"AND tb1.Type = '{type}' "; } if (!string.IsNullOrWhiteSpace(status)) { sqlPub += $"AND tb1.Status = '{status}' "; } if (!string.IsNullOrWhiteSpace(isWave)) { sqlPub += $"AND tb1.IsWave = '{isWave}' "; } if (!string.IsNullOrWhiteSpace(isDespatch)) { sqlPub += $"AND tb1.IsDespatch = '{isDespatch}' "; } if (logisticsId != null) { sqlPub += $"AND tb1.LogisticsId = '{logisticsId}' "; } sqlCount += sqlPub + "AND tb1.IsDel = '0' "; sqlPub += "AND tb1.IsDel = '0' order by tb1.SONo 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 } }