using System; using System.Collections.Generic; using System.ComponentModel.Design; using System.Linq; using System.Linq.Expressions; using System.Text; using Model.InterFaceModel; using Model.ModelDto.BllCheckDto; using Model.ModelDto.BllSoDto; using Model.ModelDto.DataDto; using Model.ModelVm.BllCheckVm; using Newtonsoft.Json; using SqlSugar; using Utility.Tools; using WMS.BLL.LogServer; using WMS.DAL; using WMS.Entity.BllAsnEntity; using WMS.Entity.BllCheckEntity; using WMS.Entity.BllSoEntity; using WMS.Entity.Context; using WMS.Entity.DataEntity; using WMS.Entity.LogEntity; using WMS.Entity.SysEntity; using WMS.IBLL.IBllCheckServer; namespace WMS.BLL.BllCheckServer { public class StockCheckServer : DbHelper, IStockCheckServer { private static readonly SqlSugarScope Db = DataContext.Db; public StockCheckServer() : base(Db) { } //获取盘点单据 public List GetStockCheckList(string crNo, string status, string palletNo, string skuNo, string skuName, string lotNo, string startTime, string endTime, int page, int limit, out int count) { try { var strList = new List(); if (!string.IsNullOrWhiteSpace(palletNo) || !string.IsNullOrWhiteSpace(skuNo) || !string.IsNullOrWhiteSpace(skuName) || !string.IsNullOrWhiteSpace(lotNo)) { Expression> demo = Expressionable.Create() .AndIF(!string.IsNullOrWhiteSpace(palletNo), m => m.PalletNo.Contains(palletNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(skuNo), m => m.SkuNo.Contains(skuNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(skuName), m => m.SkuName.Contains(skuName.Trim())) .AndIF(!string.IsNullOrWhiteSpace(lotNo), m => m.LotNo.Contains(lotNo.Trim())) .And(m => m.IsDel == "0") .ToExpression();//注意 这一句 不能少 var detailList = Db.Queryable().Where(demo).Select(m => m.CRNo).Distinct().ToList(); strList = detailList; } Expression> item = Expressionable.Create() .AndIF(!string.IsNullOrWhiteSpace(crNo), m => m.CRNo.Contains(crNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(status), m => m.Status == int.Parse(status)) .AndIF(!string.IsNullOrWhiteSpace(startTime), m => m.CheckDate >= Convert.ToDateTime(startTime)) .AndIF(!string.IsNullOrWhiteSpace(endTime), m => m.CheckDate <= Convert.ToDateTime(endTime).AddDays(1)) .AndIF(!string.IsNullOrWhiteSpace(palletNo), m => strList.Contains(m.CRNo)) .AndIF(!string.IsNullOrWhiteSpace(skuNo), m => strList.Contains(m.CRNo)) .AndIF(!string.IsNullOrWhiteSpace(skuName), m => strList.Contains(m.CRNo)) .AndIF(!string.IsNullOrWhiteSpace(lotNo), m => strList.Contains(m.CRNo)) .And(m => m.IsDel == "0") .ToExpression();//注意 这一句 不能少 var total = 0; var list = Db.Queryable().Where(item) .LeftJoin((a, b) => a.AuditUser == 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.CRNo == e.CRNo) .Select((a, b, c, d, e) => new StockCheckDto() { Id = a.Id, CrNo = a.CRNo, CheckDate = a.CheckDate, Status = a.Status, AuditStatusNo = a.AuditStatusNo, IsDoubleCheck = a.IsDoubleCheck, AuditUserName = b.RealName, AuditTime = a.AuditTime, Qty = e.Qty, //库存数量 RealQty = e.RealQty, //实际数量 PalletNo = e.PalletNo, //托盘编码 CheckResult = e.CheckResult, //盘点结果 LotNo = e.LotNo, //批次 LotText = e.LotText, //批次描述 SkuName = e.SkuName, //物料名称 SkuNo = e.SkuNo, //物料编码 ZStatus = e.Status, //执行状态 CreateUserName = c.RealName, UpdateUserName = d.RealName, CreateTime = a.CreateTime, UpdateTime = a.UpdateTime, }) .OrderByDescending(a => a.CreateTime) .ToOffsetPage(page, limit, ref total); count = total; return list; } catch (Exception e) { throw new Exception(e.Message); } } //获取盘点单据明细 public List GetStockCheckDetailList(string crNo, int page, int limit, out int count) { try { var total = 0; var list = Db.Queryable().Where(m => m.IsDel == "0" && m.CRNo == crNo) .LeftJoin((a, b) => a.CreateUser == b.Id) .LeftJoin((a, b, c) => a.UpdateUser == c.Id) .Select((a, b, c) => new StockCheckDetailDto() { Id = a.Id, CrNo = a.CRNo, PalletNo = a.PalletNo, Qty = a.Qty, RealQty = a.RealQty, CheckResult = a.CheckResult, Status = a.Status, SkuNo = a.SkuNo, SkuName = a.SkuName, Standard = a.Standard, LotNo = a.LotNo, LotText = a.LotText, SupplierLot = a.SupplierLot, CreateUserName = b.RealName, UpdateUserName = c.RealName, CreateTime = a.CreateTime, UpdateTime = a.UpdateTime, }).ToOffsetPage(page, limit, ref total); count = total; return list; } catch (Exception e) { throw new Exception(e.Message); } } //获取库存明细信息(盘点选择明细数据源) public List GetCheckStockDetailList(string houseNo, string roadwayNo, string locateNo, string skuNo, string lotNo, int page, int limit, out int count) { try { var roadway = Db.Queryable().Where(a => a.IsDel == "0" && a.WareHouseNo == "W03" && a.Status == "0").Select(a => a.RoadwayNo).ToList(); if (roadway.Count == 0) { throw new Exception("获取失败,当前巷道已被全部禁用!"); } 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(roadway.Count > 0, m => roadway.Contains(m.RoadwayNo)) .AndIF(!string.IsNullOrWhiteSpace(skuNo), m => m.SkuNo.Contains(skuNo.Trim())) .AndIF(!string.IsNullOrWhiteSpace(lotNo), m => m.LotNo.Contains(lotNo.Trim())) .And(m => m.IsDel == "0" && m.SkuNo != "100099" && m.SkuNo != "100098" && m.SkuNo != "100097" && m.SkuNo != "100096" && m.SkuNo != "100095" && m.Status == "0") .ToExpression();//注意 这一句 不能少 var total = 0; var list = Db.Queryable().Where(item).GroupBy(m => new { m.SkuNo, m.SkuName, m.Standard, m.LotNo, m.LotText, m.SupplierLot, m.LocatNo, m.PalletNo }) .Select(a => new StockDetailDto() { SkuNo = a.SkuNo, SkuName = a.SkuName, Standard = a.Standard, LotNo = a.LotNo, LotText = a.LotText, SupplierLot = a.SupplierLot, Qty = SqlFunc.AggregateSum(a.Qty), LocatNo = a.LocatNo, PalletNo = a.PalletNo }) .ToOffsetPage(page, limit, ref total).ToList(); count = total; return list; } catch (Exception e) { throw new Exception(e.Message); } } public EditStockCheckDto GetStockCheckDetailById(string crNo) { try { var notify = Db.Queryable().First(m => m.CRNo == crNo && m.IsDel == "0"); if (notify == null) { throw new Exception($"未查询到{crNo}的盘点单据信息"); } var detail = Db.Queryable().Where(m => m.CRNo == crNo && m.IsDel == "0").Select(m => new EditStockCheckDetailDto() { SkuNo = m.SkuNo, SkuName = m.SkuName, Standard = m.Standard, LotNo = m.LotNo, LotText = m.LotText, SupplierLot = m.SupplierLot, Qty = (int)m.Qty, PalletNo = m.PalletNo }).ToList(); var data = new EditStockCheckDto() { CrNo = crNo, Detail = detail }; return data; } catch (Exception e) { throw new Exception(e.Message); } } //添加盘点单、编辑盘点单 public void AddEditStockCheck(AddEditStockCheckVm model, int userId) { try { if (model.Detail.Count == 0) { throw new Exception("盘点明细不能为空"); } Db.BeginTran(); var time = DateTime.Now; //添加 if (string.IsNullOrWhiteSpace(model.CrNo)) { var num = Db.Queryable().Count(m => m.IsDel == "0" && m.Status != 3 && m.Status != 4); if (num > 0) { throw new Exception("已有等待执行或正在执行的盘点单据请先完成或删除"); } var crNo = new Common().GetMaxNo("CR"); //var stockDetail = Db.Queryable().Where(m => m.IsDel == "0"); var check = new BllStockCheck() { CRNo = crNo, Status = 0, CreateUser = userId, CreateTime = time }; var list = new List(); foreach (var item in model.Detail) { var detail = new BllStockCheckDetail() { CRNo = crNo, PalletNo = item.PalletNo, Qty = item.Qty, Status = 0, //0:未盘 1:已盘 2:已调整 SkuNo = item.SkuNo, SkuName = item.SkuName, Standard = item.Standard, LotNo = item.LotNo, LotText = item.LotText, SupplierLot = item.SupplierLot, CreateUser = userId, CreateTime = time }; list.Add(detail); var sd = Db.Queryable().First(m => m.SkuNo == item.SkuNo && m.LotNo == item.LotNo && m.PalletNo == item.PalletNo && m.Status == "0" && m.IsDel == "0"); sd.Status = "3"; Db.Updateable(sd).ExecuteCommand(); } Db.Insertable(check).ExecuteCommand(); Db.Insertable(list).ExecuteCommand(); //添加操作日志记录 var k = new OperationCrServer().AddLogOperationCr("库内作业", "盘点单据", crNo, "添加", $"添加了单据号为{crNo}的盘点单信息", userId); } else //编辑 { var check = Db.Queryable().First(m => m.IsDel == "0" && m.CRNo == model.CrNo); if (check == null) { throw new Exception("未查询到盘点单据的信息"); } check.UpdateUser = userId; check.UpdateTime = time; Db.Updateable(check).ExecuteCommand(); //盘点明细信息 var checkDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.CRNo == model.CrNo).ToList(); //删除旧的 foreach (var d in checkDetail) { var mq = model.Detail.Where(o => o.SkuNo == d.SkuNo && o.LotNo == d.LotNo && o.PalletNo == d.PalletNo).ToList(); if (mq.Any()) //如果有这个物料及批次则跳过 { continue; } var sd = Db.Queryable().Where(m => m.IsDel == "0" && m.SkuNo == d.SkuNo && m.LotNo == d.LotNo && m.PalletNo == d.PalletNo && m.Status == "3").ToList(); foreach (var s in sd) { s.Status = "0"; } d.IsDel = "1"; d.UpdateUser = userId; d.UpdateTime = time; //修改库存明细的状态(解除盘点锁定) Db.Updateable(sd).ExecuteCommand(); Db.Updateable(d).ExecuteCommand(); } //添加与修改 var list = new List(); foreach (var item in model.Detail) { var de = checkDetail.FirstOrDefault(m => m.PalletNo == item.PalletNo && m.SkuNo == item.SkuNo && m.LotNo == item.LotNo); //新加项 if (de == null) { var detail = new BllStockCheckDetail() { CRNo = model.CrNo, PalletNo = item.PalletNo, Qty = item.Qty, Status = 0, //0:未盘 1:已盘 2:已调整 SkuNo = item.SkuNo, SkuName = item.SkuName, Standard = item.Standard, LotNo = item.LotNo, LotText = item.LotText, SupplierLot = item.SupplierLot, CreateUser = userId, CreateTime = time }; list.Add(detail); var sd = Db.Queryable().Where(m => m.IsDel == "0" && m.SkuNo == item.SkuNo && m.LotNo == item.LotNo && m.PalletNo == item.PalletNo && m.Status == "0").ToList(); foreach (var s in sd) { s.Status = "3"; } Db.Updateable(sd).ExecuteCommand(); } else if (de.Qty != item.Qty) { de.Qty = item.Qty; de.UpdateUser = userId; de.UpdateTime = time; Db.Updateable(de).ExecuteCommand(); } } if (list.Count > 0) { Db.Insertable(list).ExecuteCommand(); } //添加操作日志记录 var k = new OperationCrServer().AddLogOperationCr("库内作业", "盘点单据", model.CrNo, "编辑", $"编辑了单据号为{model.CrNo}的盘点单信息", userId); } Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } //删除盘点单 public void DelStockCheck(int id, int userId) { try { var notice = Db.Queryable().First(m => m.IsDel == "0" && m.Id == id); if (notice == null || notice.Status != 0) { throw new Exception("未查询到状态为等待执行的盘点单信息"); } var detail = Db.Queryable().Where(m => m.IsDel == "0" && m.CRNo == notice.CRNo).ToList(); if (detail.Count == 0) { throw new Exception("未查询到盘点单据明细信息"); } Db.BeginTran(); var time = DateTime.Now; foreach (var d in detail) { d.IsDel = "1"; d.UpdateTime = time; d.UpdateUser = userId; var item = Db.Queryable().Where(m => m.IsDel == "0" && m.PalletNo == d.PalletNo && m.SkuNo == d.SkuNo && m.LotNo == d.LotNo && m.Status == "3").ToList(); foreach (var i in item) { i.Status = "0"; } Db.Updateable(item).ExecuteCommand(); } notice.IsDel = "1"; notice.UpdateTime = time; notice.UpdateUser = userId; Db.Updateable(notice).ExecuteCommand(); Db.Updateable(detail).ExecuteCommand(); //添加操作日志记录 var k = new OperationCrServer().AddLogOperationCr("库内作业", "盘点单据", notice.CRNo, "删除", $"删除了单据号为{notice.CRNo}的盘点单信息", userId); Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } //调整库存 public bool StockAdjust(int id, int userId) { try { #region 判断 var notice = Db.Queryable().First(m => m.IsDel == "0" && m.Id == id); if (notice == null || notice.Status != 2) { throw new Exception("未查询到状态为盘点完成的盘点单信息"); } var detail = Db.Queryable().Where(m => m.IsDel == "0" && m.CRNo == notice.CRNo).ToList(); if (detail.Count == 0) { throw new Exception("未查询到盘点单据明细信息"); } #endregion Db.BeginTran(); //开启事务 //盘点总表 var check = Db.Queryable().First(m => m.IsDel == "0" && m.Id == id); //盘点明细 var checkDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.CRNo == check.CRNo).ToList(); //盘点记录 var checkLog = Db.Queryable().Where(m => m.IsDel == "0" && m.CRNo == check.CRNo).ToList(); //对应库存记录 //时间 var time = DateTime.Now; //循环盘点明细 foreach (var item in checkDetail) { //根据盘点明细物料信息获取库存明细 var dataStockDetail = Db.Queryable().First(m => m.IsDel == "0" && m.PalletNo == item.PalletNo && m.SkuNo == item.SkuNo && m.SkuName == item.SkuName && m.LotNo == item.LotNo); //根据盘点明细物料信息获取库存表 var dataStock = Db.Queryable().First(m => m.IsDel == "0" && m.SkuNo == item.SkuNo && m.SkuName == item.SkuName && m.LotNo == item.LotNo); //根据盘点明细物料信息获取托盘绑定信息 var palletBind = Db.Queryable().First(m => m.IsDel == "0" && m.LotNo == item.LotNo && m.PalletNo == item.PalletNo); //判断托盘绑定信息是否为空 if (palletBind == null) { throw new Exception("未查询到托盘绑定信息,请核查!"); } item.Status = 4; //库存明细 4:已调整 item.UpdateTime = time; //修改时间 item.UpdateUser = userId; //修改人 //获取实际数量减去系统数量 var num = 0; //判断盘点明细表中盘点状态为什么 //正常 if (item.CheckResult == 0) { //正常则不改变任何数量 改变库存明细 dataStockDetail.Status = "0"; //状态改为 0:待分配 Db.Updateable(dataStockDetail).ExecuteCommand(); //库存明细表 } //盘亏\盘盈 else if (item.CheckResult == 1 || item.CheckResult == 2) { //获取对应物料当天库存信息 string strinfo = $"select top 1 * from DataStockInfo where IsDel = '0' and SkuNo = '{item.SkuNo}' order by CreateTime desc"; var datainfo = Db.Ado.SqlQuerySingle(strinfo); if (item.CheckResult == 1) { //盘亏 系统数量减去实际数量 num = (int)item.Qty - (int)item.RealQty; //库存总表数量为实际数量 dataStock.Qty -= num; Db.Updateable(dataStock).ExecuteCommand(); //库存表 } else if (item.CheckResult == 2) { //盘盈 实际数量减去系统数量 num = (int)item.RealQty - (int)item.Qty; //库存总表数量为实际数量 dataStock.Qty += num; Db.Updateable(dataStock).ExecuteCommand(); //库存表 } //库存明细表根据托盘修改数量 dataStockDetail.Qty = (int)item.RealQty; dataStockDetail.Status = "0"; //状态改为 0:待分配 dataStockDetail.BitPalletMark = item.RealQty == palletBind.FullQty ? "0" : "1"; //判断是否满托 Db.Updateable(dataStockDetail).ExecuteCommand(); //库存明细表 #region 库存记录 //datainfo.ArrivalQty += 0;//入库数量 datainfo.ExportQty += (int)item.RealQty;//入库数量 datainfo.BalanceQty += (int)item.RealQty;//结存数量 datainfo.YearBalanceQty += (int)item.RealQty;//结存数量(月) datainfo.YearExportQty += (int)item.RealQty;//入库数量(月) Db.Updateable(datainfo).ExecuteCommand(); #endregion } Db.Updateable(item).ExecuteCommand(); //盘点明细表 } //修改盘点总表信息 check.Status = 3; //状态为3:已调整 check.AuditTime = time; //操作时间 check.AuditUser = userId; //操作人 Db.Updateable(check).ExecuteCommand();//修改盘点总表 //添加操作日志记录 var k = new OperationCrServer().AddLogOperationCr("库内作业", "盘点单据", check.CRNo, "调整", $"调整了单据号为{check.CRNo}的盘点单信息", userId); Db.CommitTran(); return true; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } //throw new NotImplementedException(); } //作废盘点单 public bool ZuofeiCr(int id, int userId) { try { #region 判断 var notice = Db.Queryable().First(m => m.IsDel == "0" && m.Id == id); if (notice == null || notice.Status != 2) { throw new Exception("未查询到状态为盘点完成的盘点单信息"); } var detail = Db.Queryable().Where(m => m.IsDel == "0" && m.CRNo == notice.CRNo).ToList(); if (detail.Count == 0) { throw new Exception("未查询到盘点单据明细信息"); } #endregion Db.BeginTran(); //开启事务 //盘点总表 var check = Db.Queryable().First(m => m.IsDel == "0" && m.Id == id); //盘点明细 var checkDetail = Db.Queryable().Where(m => m.IsDel == "0" && m.CRNo == check.CRNo).ToList(); //时间 var time = DateTime.Now; //循环盘点明细 foreach (var item in checkDetail) { //根据盘点明细物料信息获取库存明细 var dataStockDetail = Db.Queryable().First(m => m.IsDel == "0" && m.PalletNo == item.PalletNo && m.SkuNo == item.SkuNo && m.SkuName == item.SkuName && m.LotNo == item.LotNo); dataStockDetail.Status = "0"; //状态改为 0:待分配 Db.Updateable(dataStockDetail).ExecuteCommand(); //库存明细表 } //修改盘点总表信息 check.Status = 4; //状态为4:已作废 check.AuditTime = time; //操作时间 check.AuditUser = userId; //操作人 Db.Updateable(check).ExecuteCommand();//修改盘点总表 //添加操作日志记录 var k = new OperationCrServer().AddLogOperationCr("库内作业", "盘点单据", check.CRNo, "作废", $"作废了单据号为{check.CRNo}的盘点单信息", userId); Db.CommitTran(); return true; } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } //throw new NotImplementedException(); } //盘点下发出库 public List CheckOutHouse(string crNo, int userId, string url, out string str) { try { //测试url 发布服务器后删除 //url = "http://localhost:57061/api/WCSApi/AddTasks"; #region 集合 //获取未锁定巷道 var roadway = Db.Queryable().Where(a => a.IsDel == "0" && a.WareHouseNo == "W03" && a.Status == "0").Select(a => a.RoadwayNo).ToList(); //验证是否存在未锁定巷道 if (roadway.Count == 0) { throw new Exception("当前无未锁定巷道,请解除!"); } var outDtoList = new List(); //出库数据的集合 var outDtoList1 = 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.CRNo == crNo && m.IsDel == "0"); if (notice == null) { throw new Exception($"未找到{crNo}盘点单信息"); } //所有要出库的盘点明细信息(等待的信息和待拣货的信息) var list = Db.Queryable().Where(a => a.IsDel == "0" && a.CRNo == crNo && (a.Status == 0 || a.Status == 1)).ToList(); if (list.Count == 0) //判断是否有需要下发的盘点明细 { throw new Exception("当前盘点单据无需要下发的托盘"); } #region //要出库的托盘集合 var outLpnList = list.Select(m => m.PalletNo).Distinct().ToList(); //要出库的明细集合 var outStockDetail = Db.Queryable().Where(m => m.IsDel == "0" && roadway.Contains(m.RoadwayNo) && outLpnList.Contains(m.PalletNo)).ToList(); var outStockBox = Db.Queryable().Where(m => m.IsDel == "0" && outLpnList.Contains(m.PalletNo)).ToList(); if (outStockDetail.Count == 0) { throw new Exception("当前未禁用巷道无可分配货物不足,禁止出库!"); } int? dataStockQtyCount = 0; foreach (var item in outStockDetail) { dataStockQtyCount += item.Qty; if (dataStockQtyCount >= list[0].Qty) { break; } } if (dataStockQtyCount < list[0].Qty) { throw new Exception("当前未禁用巷道可分配货物不足,禁止出库!"); } var time = DateTime.Now; Db.BeginTran(); try { //循环盘点明细的信息生成出库任务 foreach (var item in list) { var taskNoStr = ""; //获取物料信息 var sku = Db.Queryable().First(m => m.IsDel == "0" && m.SkuNo == item.SkuNo); if (item.Status == 0) { var de = outStockDetail.Where(m => m.SkuNo == item.SkuNo && m.LotNo == item.LotNo && m.PalletNo == item.PalletNo).Select(m => m.Id).ToList(); var bo = outStockBox.Where(m => de.Contains(m.StockDetailId)).ToList(); var logList = new List(); foreach (var b in bo) { var checkLog = new BllStockCheckLog() { CRNo = item.CRNo, PalletNo = item.PalletNo, BoxNo = b.BoxNo, BoxNo2 = b.BoxNo2, BoxNo3 = b.BoxNo3, Qty = b.Qty, SkuNo = b.SkuNo, SkuName = b.SkuName, Standard = b.Standard, LotNo = b.LotNo, LotText = b.LotText, SupplierLot = b.SupplierLot, CreateUser = userId, CreateTime = time }; logList.Add(checkLog); } Db.Insertable(logList).ExecuteCommand(); } // 储位号 var locateNo = outStockDetail.First(m => m.PalletNo == item.PalletNo && m.SkuNo == item.SkuNo && m.LotNo == item.LotNo).LocatNo; #region 判断 //判断托盘是否在库内 if (string.IsNullOrWhiteSpace(locateNo)) { //判断托盘是否在入库中 var imBl = com.GetImTask(item.PalletNo); if (imBl != null) { flagList.Add(4); continue; } //判断是否是已经出过库又回库(状态为待拣货的 1) if (item.Status == 0) { //如果不在仓库内,当前明细信息直接更新出库完成 item.Status = 2;//状态 Db.Updateable(item).ExecuteCommand(); } continue; } //当前出库的储位信息 var locate = Db.Queryable().First(m => m.LocatNo == locateNo && m.IsDel == "0"); if (locate == null) { flagList.Add(2); continue; } //判断储位标志是否为损坏 if (locate.Flag == "2") { flagList.Add(3); continue; } #endregion if (locate.Status == "1") //有物品 { #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 = "",//目标位置 PalletNo = item.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "2",//0 入库单 1 出库单 2 盘点单 3 移库单 CreateTime = time, Msg = locate.LocatNo + "==>>的盘点任务" }; Db.Insertable(exTask).ExecuteCommand(); outDtoList1.Add(new OutCommandDto() { SkuType = sku.Type, //物料类型 StartRoadway = locate.RoadwayNo, //巷道号 PalletNo = item.PalletNo,//托盘号 StartLocat = locate.LocatNo, // 起始位置 EndLocat = "28", // 目标位置 TaskNo = exTask.TaskNo, // 任务号 Type = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1, LotNo = item.LotNo, IsBale = "0", IsBelt = "0", PalletType = outStockDetail.First(m => m.PalletNo == item.PalletNo && m.SkuNo == item.SkuNo && m.LotNo == item.LotNo).PalletType }); } else if (locate.Depth == "02") //深度为2 { //获取出库深度为2储位前面的储位信息 var slotBefore = com.GetLocateNoDepth1(locate.WareHouseNo, locate.LocatNo); if (slotBefore.Status == "1") //前面的储位有货物、进行移库操作 { //要出库深度为2的储位前面的储位中货物是否要出库 var isout = outStockDetail.Count(m => m.LocatNo == slotBefore.LocatNo); if (isout <= 0) //进行移库 { //去库存表中找到储位对应的托盘码操作 var stockNew = Db.Queryable().First(m => m.LocatNo == slotBefore.LocatNo); if (stockNew == null) { var slotChange = Db.Queryable().First(m => m.LocatNo == slotBefore.LocatNo); slotChange.Status = "0"; Db.Updateable(slotChange).ExecuteCommand(); } else { //获取移库的库位 var newSlot = MoveAddress(slotBefore.LocatNo, slotBefore.RoadwayNo, slotBefore.AreaNo); //当前移库库位的储位信息 var locatey = Db.Queryable().First(m => m.LocatNo == newSlot && m.IsDel == "0"); if (!string.IsNullOrEmpty(newSlot)) { #region 添加出库时发生的移库任务 var exYkTaskNo = new Common().GetMaxNo("TK"); var exYkTask = new LogTask //出库时产生移库任务 { TaskNo = exYkTaskNo, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = stockNew.LocatNo,//起始位置 EndLocat = newSlot,//目标位置 PalletNo = stockNew.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "2",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "2",//0 入库单 1 出库单 2 盘点单 3 移库单 CreateTime = time, Msg = stockNew.LocatNo + " ==>> " + newSlot + "的移库任务", }; Db.Insertable(exYkTask).ExecuteCommand(); moveDto.Add(new OutCommandDto() { SkuType = sku.Type, //物料类型 StartRoadway = slotBefore.RoadwayNo, //起始巷道 PalletNo = stockNew.PalletNo,//托盘号 StartLocat = stockNew.LocatNo, // 起始位置 EndLocat = newSlot, // 目标位置 EndRoadway = locatey.RoadwayNo, // 目标巷道 TaskNo = exYkTask.TaskNo, // 任务号 Type = "2",// 任务类型 (移库) OutMode = "", //目标地址 Order = 1, LotNo = stockNew.LotNo, Qty = 0, //拣货数量 FullQty = (int)stockNew.Qty, //托盘数量 //PalletType = stockNew.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘 }); #endregion #region 改变储位装填 var slotChange = Db.Queryable().First(m => m.Id == slotBefore.Id); var slotChange2 = Db.Queryable().First(m => m.LocatNo == newSlot); slotChange.Status = "5"; //改变状态(正在移出) slotChange2.Status = "4"; // 改变状态(正在移入) Db.Updateable(slotChange).ExecuteCommand(); Db.Updateable(slotChange2).ExecuteCommand(); #endregion } else { #region 添加出库任务 var exYkTaskNo1 = new Common().GetMaxNo("TK"); var exYkTask1 = new LogTask //出库移库没有库位了进行出库任务 { TaskNo = exYkTaskNo1, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = stockNew.LocatNo,//起始位置 EndLocat = "",//目标位置 PalletNo = stockNew.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "2",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = locate.LocatNo + "的出库任务" }; Db.Insertable(exYkTask1).ExecuteCommand(); outDtoList1.Add(new OutCommandDto() { SkuType = sku.Type, //物料类型 StartRoadway = slotBefore.RoadwayNo, //起始巷道 PalletNo = stockNew.PalletNo,//托盘号 StartLocat = stockNew.LocatNo, // 起始位置 EndLocat = "", // 目标位置 TaskNo = exYkTask1.TaskNo, // 任务号 Type = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1, LotNo = "", // 批次 IsBale = "0", //是否裹包 IsBelt = "0", //是否打带 //IsStacking1 = item.IsAdvance, //是否拆桶(08暂定) Qty = 0, //拣货数量 FullQty = (int)stockNew.Qty, //托盘数量 PalletType = stockNew.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘 }); #endregion #region MyRegion var slotChange = Db.Queryable().First(m => m.Id == slotBefore.Id); slotChange.Status = "3"; //改变状态(正在出库) Db.Updateable(slotChange).ExecuteCommand(); #endregion } } } } else if (slotBefore.Status == "2" || slotBefore.Status == "4") //前面储位状态是入库中或者移入中 { flagList.Add(5); continue; } #region 添加出库任务 var taskNo1 = new Common().GetMaxNo("TK"); var exTask1 = new LogTask //出库任务 { TaskNo = taskNo1, Sender = "WMS", Receiver = "WCS", IsSuccess = 0, //是否下发成功 0失败 1成功 StartLocat = locate.LocatNo,//起始位置 EndLocat = "",//目标位置 PalletNo = item.PalletNo,//托盘码 IsSend = 1,//是否可再次下发 IsCancel = 1,//是否可取消 IsFinish = 1,//是否可完成 Type = "1",//任务类型 0 入库任务 1 出库任务 2 移库任务 Status = "0",//任务状态0:等待执行1正在执行2执行完成 OrderType = "2",//0 入库单 1 出库单 2 盘点单 3 移库单 Msg = locate.LocatNo + "的出库任务" }; Db.Insertable(exTask1).ExecuteCommand(); outDtoList1.Add(new OutCommandDto() { SkuType = sku.Type, //物料类型 StartRoadway = locate.RoadwayNo, //起始巷道 PalletNo = item.PalletNo,//托盘号 StartLocat = locate.LocatNo, // 起始位置 EndLocat = "", // 目标位置 TaskNo = exTask1.TaskNo, // 任务号 Type = "1",// 任务类型 (出库) OutMode = "", //目标地址 Order = 1, IsBale = "0", //是否裹包 IsBelt = "0", //是否打带 IsStacking1 = "0", //是否拆桶(08暂定) Qty = (int)item.Qty, //拣货数量 //FullQty = (int)item.BoxexQty, //托盘数量 //PalletType = stockDetail.PalletType, //托盘类型(有无子托)0||空||null:无子托盘1:有子托盘 }); taskNoStr = exTask1.TaskNo; #endregion } #endregion #region 改变数据 if (item.Status == 0)//判断托盘是否下发过 { } locate.Status = "3"; //要出库的储位改变状态 正在出库 Db.Updateable(locate).ExecuteCommand(); item.TaskNo = taskNoStr; // 出库分配信息中更新任务号 item.Status = 1; // 出库分配信息状态改为正在执行 Db.Updateable(item).ExecuteCommand(); #endregion flagList.Add(0); } else if (locate.Status == "3") //出库中 { #region 改变数据 //判断是否是已经出过库又回库(状态为待拣货的 1) if (item.Status == 0) { } var taskNo = Db.Queryable().First(m => m.OrderType == "2" && m.TaskNo != item.TaskNo && m.Status == "1" && m.PalletNo == item.PalletNo); item.TaskNo = taskNo.TaskNo; item.Status = 1; // 出库分配信息状态改为正在执行 Db.Updateable(item).ExecuteCommand(); #endregion } else if (locate.Status == "5") //移出中 { flagList.Add(1); } } //先移库后出库 outDtoList.AddRange(moveDto); outDtoList.AddRange(outDtoList1); if (outDtoList.Count > 0) { if (notice.Status == 0) { notice.Status = 1; notice.UpdateUser = userId; notice.UpdateTime = time; notice.CheckDate = time; Db.Updateable(notice).ExecuteCommand(); } } //添加操作日志记录 var k = new OperationCrServer().AddLogOperationCr("库内作业", "盘点单据", crNo, "出库", $"点击出库按钮盘点单号为:{crNo}的盘点单", userId); str = string.Empty; 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 (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.stateCode == 0) { //更改任务的发送返回时间// new TaskServer().EditTaskIssueOk(list2, time1, time2); str += "下发成功"; } if (wcsModel.stateCode == -1) { new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.errMsg); throw new Exception(wcsModel.errMsg); } } catch (Exception ex) { throw new Exception(ex.Message); } } Db.CommitTran(); return outDtoList; } catch (Exception e) { throw new Exception(e.Message); } #endregion } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } //盘点出库完成 public void CheckSuccess(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($"未查询到任务号为:‘{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); task.Status = "2";//任务状态 task.IsSend = 0; task.IsCancel = 0; task.IsFinish = 0; task.FinishDate = DateTime.Now;//完成时间 Db.Updateable(task).ExecuteCommand(); locate.Status = "0"; // 更改当前任务中的储位状态(改为0空储位) Db.Updateable(locate).ExecuteCommand(); foreach (var item in stockDetail) { //获取对应物料当天库存信息 string strinfo = $"select top 1 * from DataStockInfo where IsDel = '0' and SkuNo = '{item.SkuNo}' order by CreateTime desc"; var datainfo = Db.Ado.SqlQuerySingle(strinfo); item.LocatNo = "";//储位更改(改为空) item.WareHouseNo = "";//所属仓库更改(改为空) item.RoadwayNo = "";//所属巷道更改(改为空) item.AreaNo = "";//所属区域更改(改为空) item.Status = "0"; //分配状态(改为待分配) Db.Updateable(item).ExecuteCommand(); #region 库存记录 datainfo.ExportQty += item.LockQty.Value;//出库数量 datainfo.BalanceQty -= item.LockQty.Value;//结存数量 datainfo.YearBalanceQty -= item.LockQty.Value;//结存数量(月) datainfo.YearExportQty += item.LockQty.Value;//出库数量(月) Db.Updateable(datainfo).ExecuteCommand(); #endregion } //盘点明细(更改状态) var checkDetails = Db.Queryable().Where(m => m.IsDel == "0" && (m.TaskNo == taskNo || (m.Status == 1 && m.PalletNo == task.PalletNo))).ToList(); foreach (var item in checkDetails) { item.Status = 2; } Db.Updateable(checkDetails).ExecuteCommand(); if (userId != 0) { //添加操作日志记录 var k = new OperationCrServer().AddLogOperationCr("库内作业", "库内日志", taskNo, "完成", $"点击完成按钮、完成任务号为:{taskNo}的任务", userId); // 正式运行程序放开 var jsonData = JsonConvert.SerializeObject(task); 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); } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } Db.CommitTran(); } catch (Exception ex) { Db.RollbackTran(); throw new Exception("完成反馈失败:" + ex.Message); } } /// /// 取消盘点出库任务 /// /// /// public void ExportSuccess(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($"未查询到任务号为:‘{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); task.Status = "3";//任务状态 3:已取消 task.IsSend = 1; //是否可再次下发 task.IsCancel = 0; //是否可取消 task.IsFinish = 0; //是否可完成 task.CancelDate = DateTime.Now;//取消时间 Db.Updateable(task).ExecuteCommand(); //获取移库任务对应目标储位信息 SysStorageLocat endlocat = new SysStorageLocat(); if (task.Type == "2") { endlocat = Db.Queryable().First(a => a.IsDel == "0" && a.WareHouseNo == "W03" && a.LocatNo == task.EndLocat); if (endlocat == null) { throw new Exception("未查询到目标储位信息"); } } locate.Status = "1"; // 更改当前任务中的储位状态(改为有物品) Db.Updateable(locate).ExecuteCommand(); if (endlocat != null) { endlocat.Status = "0"; //空储位 0 Db.Updateable(endlocat).ExecuteCommand(); } foreach (var item in stockDetail) { //修改库存明细 状态改为待分配 item.Status = "0"; //状态改为0:待分配 item.LockQty -= item.Qty; //锁定数量减少 Db.Updateable(item).ExecuteCommand(); } //盘点明细(更改状态) var checkDetails = Db.Queryable().Where(m => m.IsDel == "0" && (m.TaskNo == taskNo || (m.Status == 1 && m.PalletNo == task.PalletNo))).ToList(); foreach (var item in checkDetails) { item.Status = 0; //盘点明细状态改为为0:待下发 } Db.Updateable(checkDetails).ExecuteCommand(); if (userId != 0) { //添加操作日志记录 var k = new OperationCrServer().AddLogOperationCr("库内作业", "库内日志", taskNo, "取消", $"点击取消按钮、完成任务号为:{taskNo}的任务", userId); // 正式运行程序放开 var jsonData = JsonConvert.SerializeObject(task); 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); } catch (Exception ex) { Db.RollbackTran(); throw new Exception(ex.Message); } } Db.CommitTran(); } catch (Exception ex) { Db.RollbackTran(); throw new Exception("完成反馈失败:" + ex.Message); } } /// /// 获取移库目标库位 /// /// 需要移动的库位地址 /// 巷道 /// 区域 /// 目标库位地址 为"" 直接下发两次出库指令 public string MoveAddress(string oldAddress, string roadWay, string area)//01020201 排-列-层-深度 { string nowAddress = ""; // 获取移库目标储位 var row = int.Parse(oldAddress.Substring(0, 2)); var lie = int.Parse(oldAddress.Substring(2, 2)); var ceng = int.Parse(oldAddress.Substring(4, 2)); var sqlString = $@"select LocatNo,[Row],[Column],Layer, (ABS(Row-{row}) + ABS([Column]-{lie}) + ABS(Layer-{ceng})) as distNum from SysStorageLocat where Flag = '0' and Status = '0' and Depth = '02' and RoadwayNo = '{roadWay}' and AreaNo = '{area}' order by distNum;"; var addressModels = Db.Ado.SqlQuery(sqlString).ToList(); if (addressModels.Count > 0) // 判断同巷道内排空库位 { var listLocaete = new List(); foreach (var item in addressModels) { // 目标内库位对应的外库位 string addressee = item.LocatNo.Substring(0, 6) + "01"; // 判断目标库位的外库位是否存在货物 (正常情况下正在移入情况不存在,因为移库先移入里面,后移入外面) //SlotStatus 0: 空储位 1:有货 2:正在入库 3:正在出库 4:正在移入 5:正在移出 sqlString = $"select count(*) from SysStorageLocat where LocatNo = '{addressee}' and Status = '0' and Flag in ('0','1') ; "; var rowNum = Db.Ado.SqlQuery(sqlString).First(); if (rowNum == 0) { continue; } else { nowAddress = item.LocatNo; break; } } } if (nowAddress == "") { // 判断同巷道外排空库位 sqlString = $@"select LocatNo,[Row],[Column],Layer, (ABS(Row-{row}) + ABS([Column]-{lie}) + ABS(Layer-{ceng})) as distNum from SysStorageLocat where Flag = '0' and Status = '0' and Depth = '01' and RoadwayNo = '{roadWay}' and AreaNo = '{area}' order by distNum;"; var adderModeling = Db.Ado.SqlQuery(sqlString).ToList(); if (adderModeling.Count > 0) { nowAddress = adderModeling[0].LocatNo; } else { // 库内不存在空储位 nowAddress = ""; } } return nowAddress; } #region 上游系统接口 //盘点结果返回erp public bool FinishCr(int id, string url, int userId) { try { Db.BeginTran(); try { } catch (Exception e) { Console.WriteLine(e); throw; } throw new NotImplementedException(); Db.CommitTran(); } catch (Exception e) { Db.RollbackTran(); throw new Exception(e.Message); } } #endregion } }