using AutoMapper; using Microsoft.Extensions.Logging; using SqlSugar; using System; using System.Collections.Generic; using System.Data; using System.Globalization; using System.Linq; using WCS.Entity.sx; using wms.dto; using wms.dto.request.sx; using wms.dto.response; using wms.dto.response.hj; using wms.dto.response.sx; using wms.service.Service; using wms.sqlsugar; using wms.sqlsugar.model.sx; using wms.util.Check; using wms.util.Ext; namespace wms.service.Help { /// /// 时效服务扩展 /// public static class SxServiceHelp { #region 焊点计算 /// /// 装箱时处理焊点盘 /// /// 箱号对应的装箱规则 /// 库存信息 /// 后续可用的不带焊点盘信息 /// 填充后的焊点盘列表 public static List ProcessWeldingPointsBoxing(BillPboxrule rule, IEnumerable? invlist, out IEnumerable? outInvlist) { var solderinvlist = new List(); invlist ??= Enumerable.Empty(); // 如果不控制焊点盘数,则直接按生产时间排序后返回 if (rule.SolderMaxCount <= 0) { outInvlist = invlist.OrderBy(p => p.ProductTime); return solderinvlist; } // 计算需要获取的焊点盘数量 int itemsPerBox = rule.SpoolType == "BS60" || rule.SpoolType == "BS40" ? 72 : 36; int requiredSolderBoxes = Math.Max(0, rule.FullCountQty / itemsPerBox * rule.SolderMaxCount); // 获取所有带焊点的盘并排序 var availableSolders = invlist.Where(p => p.SolderCount > 0).OrderBy(p => p.ProductTime).ThenByDescending(p => p.SolderCount).ToList(); // 根据是否管控总焊点数量来选择不同的策略 if (rule.PerSolderMaxCount <= 0) { // 不管控总焊点数量,直接取前 N 个 solderinvlist = availableSolders.Take(requiredSolderBoxes).ToList(); } else { // 管控总焊点数量,使用 GetWeldingPointsBoxing 方法 solderinvlist = GetWeldingPointsBoxing( currentBoxes: solderinvlist, maxBoxCount: requiredSolderBoxes, maxTotalSolderCount: rule.PerSolderMaxCount, inventory: availableSolders ); } // 剩余可用库存为无焊点的 outInvlist = invlist.Where(p => p.SolderCount == 0); return solderinvlist; } /// /// 获取焊点盘(装箱处理) /// /// 已有的焊点盘 /// 最大焊点盘数 /// 最大焊点总数 /// 库存信息 /// 填充后的焊点盘列表 public static List GetWeldingPointsBoxing(List currentBoxes, int maxBoxCount, int maxTotalSolderCount, IEnumerable? inventory) { if (inventory == null || !inventory.Any()) return currentBoxes; // 当前状态统计 var currentBoxCount = currentBoxes.Count; var currentTotalSolderCount = currentBoxes.Sum(x => x.SolderCount); // 如果已经满载,直接返回 if (currentBoxCount >= maxBoxCount || currentTotalSolderCount >= maxTotalSolderCount) return currentBoxes; // 将库存转换为列表并排序,避免重复排序 var availableInventory = inventory.Where(p => p.SolderCount > 0).OrderBy(p => p.ProductTime).ThenByDescending(p => p.SolderCount).ToList(); foreach (var item in availableInventory) { // 判断是否还能继续添加 if (currentBoxCount >= maxBoxCount || currentTotalSolderCount >= maxTotalSolderCount) break; // 添加当前项 currentBoxes.Add(item); currentBoxCount++; currentTotalSolderCount += item.SolderCount; } return currentBoxes; } #endregion 焊点计算 #region 获取码垛位 /// /// 根据配置信息获取可用码垛位 /// /// 现有码垛位 /// 配置表 /// 配置信息code /// public static List GetAvailablePalletizingStationsByConfiguration(this List palletizingList, Repository config, string code) { // 获取配置中的机器人列表 var configuredRobots = config.GetFirst(x => x.Code == code).SContent.Split("|").Select(x => ToTitleCase(x)); // 定义机器人及其对应的码垛位映射关系 var robotToPalletizingMap = new Dictionary> { { "Robot1", new List { "8090", "8092" } }, { "Robot2", new List { "8096", "8098" } }, { "Robot3", new List { "8307" } } }; // 获取所有符合条件的码垛位 var availablePalletizingCodes = configuredRobots .SelectMany(robot => { if (robotToPalletizingMap.TryGetValue(robot, out var palletizing)) { return palletizing; } return Enumerable.Empty(); }) .Distinct(); // 返回匹配的码垛位列表 return palletizingList.Where(palletizing => availablePalletizingCodes.Contains(palletizing.Code)).ToList(); } /// /// 根据配置信息获取可用机械臂 /// /// 现有码垛位 /// 配置表 /// 配置信息code /// public static List GetAvailablePalletizingRobotsByConfiguration(this List palletizingList, Repository config, string code) { // 获取配置中的机器人列表 var configuredRobots = config.GetFirst(x => x.Code == code).SContent.Split("|").Select(x => ToTitleCase(x)); // 返回匹配的码垛位列表 return palletizingList.Select(x => ToTitleCase(x)).Where(x => configuredRobots.Contains(x)).ToList(); } /// /// 将字符串转换为首字母大写,其他全小写 /// /// /// public static string ToTitleCase(string str) { if (string.IsNullOrEmpty(str)) { return str; } // 将字符串转换为全小写 string lowerStr = str.ToLower(); // 使用 TextInfo.ToTitleCase 转换为标题大小写 TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo; string titleCasedStr = textInfo.ToTitleCase(lowerStr); return titleCasedStr; } #endregion 获取码垛位 #region 分配货位 /// /// 申请入库货位 /// /// 申请信息 /// 任务表 /// 仓库表 /// 库存表 /// 货位表 /// 数据库连接 /// 映射器 /// 日志 /// public static SRes> ApplyStockInLocTemp( this SxApplyStockInLocRequest reqEntity, RepositoryTask _wcstaskoldrepository, Repository _basewarehouserepository, Repository _billInvnowrepository, Repository _basewarecellrepository, ITenant _db, IMapper _mapper, ILogger _logger) { var result = new SRes>() { ResData = new List() }; var wcstask = _wcstaskoldrepository.AsQueryable().With(SqlWith.NoLock).Where(p => reqEntity.TaskNum.Contains(p.Id) && p.Status < TaskStatus.Finish).SplitTable(tabs => tabs.Take(2)).ToList(); if (!wcstask.Any()) { result.ResCode = ResponseStatusCodeEnum.WcsTaskNotExist.GetHashCode(); result.ResMsg = string.Join(",", reqEntity.TaskNum) + ResponseStatusCodeEnum.WcsTaskNotExist.GetDescription(); return result; } if (wcstask.Any(p => p.Type == TaskType.OutDepot)) { result.ResCode = ResponseStatusCodeEnum.ErrParam.GetHashCode(); result.ResMsg = "该任务是出库任务,不能分配货位;wms任务号" + string.Join(",", reqEntity.TaskNum); return result; } if (reqEntity.TaskNum.Count != wcstask.Count) { result.ResCode = ResponseStatusCodeEnum.Fail.GetHashCode(); result.ResMsg = string.Join(',', reqEntity.TaskNum) + "申请的任务数与实际任务数不符"; return result; } var warehouse = _basewarehouserepository.GetFirst(p => p.Code == "sxhouse"); if (warehouse == null) { result.ResCode = ResponseStatusCodeEnum.WarehouseCodeNotExist.GetHashCode(); result.ResMsg = ResponseStatusCodeEnum.WarehouseCodeNotExist.GetDescription(); return result; } var stocklist = _billInvnowrepository.GetList(p => wcstask.Select(p => p.BarCode).Contains(p.ContGrpBarCode) && p.InvStateCode == InvState.InvEcecState_BuildUp.ToString()); if (!stocklist.Any()) { result.ResCode = ResponseStatusCodeEnum.StockNotExist.GetHashCode(); result.ResMsg = string.Join(",", reqEntity.TaskNum) + ResponseStatusCodeEnum.StockNotExist.GetDescription(); return result; } if (reqEntity.TaskNum.Count != stocklist.Count) { result.ResCode = ResponseStatusCodeEnum.StockNotExist.GetHashCode(); result.ResMsg = string.Join(",", reqEntity.TaskNum) + "申请的任务数与库存数量不符"; return result; } if (wcstask.Count > 1) { List list = new List(); var code = string.Empty; var num = new List() { reqEntity.TaskNum[1], reqEntity.TaskNum[0] }; foreach (var item in num) { //验证库存 var task = wcstask.Where(p => p.Id == item).First(); var stock = stocklist.Where(p => p.ContGrpBarCode == task.BarCode).First(); if (!string.IsNullOrEmpty(task.AddrTo) && task.Fork != 0) { var applyCell = new ApplyStockInLocResponse() { TunnelNum = reqEntity.TunnelNum.ToString(), CellNo = task.AddrTo, Row = task.AddrTo.Split('-')[0] != null ? int.Parse(task.AddrTo.Split('-')[0]) : 0, Colomn = task.AddrTo.Split('-')[1] != null ? int.Parse(task.AddrTo.Split('-')[1]) : 0, Layer = task.AddrTo.Split('-')[2] != null ? int.Parse(task.AddrTo.Split('-')[2]) : 0, Fork = task.Fork, TaskNo = task.Id }; result.ResData.Add(applyCell); continue; } if (!string.IsNullOrEmpty(code)) { var cell2 = ApplyLoc(new ApplyLocRequest() { MaterialId = stock.MatId, MaterialCode = stock.MatCode, TunnelNum = reqEntity.TunnelNum, WarehuoseId = warehouse.Id, IsMove = task.Type == TaskType.TransferDepot, Floor = reqEntity.Floor, CellCode = code, Fork = 2, Wind = stock.Wind, IsControlpanel = stock.IsControlpanel, IsTorsChk = stock.IsTorsChk, TorsChkQty = stock.TorsChkQty, ProductTime = stock.ProductTime, Wbgroup = stock.WbGroupCode }, _basewarecellrepository, _basewarehouserepository, _billInvnowrepository, _logger); if (cell2.ResCode != ResponseStatusCodeEnum.Sucess.GetHashCode()) { result.ResCode = cell2.ResCode; result.ResMsg = item + cell2.ResMsg; return result; } try { cell2.ResData.Fork = 2; cell2.ResData.TaskNo = item; _db.BeginTran(); _wcstaskoldrepository.AsUpdateable().SetColumns(p => new WCS_TaskOld() { AddrTo = cell2.ResData.CellNo, Fork = cell2.ResData.Fork }).Where(p => p.Id == item).SplitTable(p => p.Take(2)).ExecuteCommand(); _basewarecellrepository.UpdateModelColumns(p => new BaseWarecell() { StateNum = LocationState.LocationState_StockIn, ContGrpBarCode = "", ContGrpId = 0, EditTime = DateTime.Now }, p => cell2.ResData.CellNo == p.Code); _db.CommitTran(); result.ResData.Add(_mapper.Map(cell2.ResData)); } catch (Exception ex) { _db.RollbackTran(); result.ResCode = ResponseStatusCodeEnum.Fail.GetHashCode(); result.ResMsg = item + ResponseStatusCodeEnum.DataSaveErr.GetDescription() + ex.Message; return result; } continue; } #region 处理两个任务都是一货叉情况 if (item == reqEntity.TaskNum[0]) { var cell2 = ApplyLoc(new ApplyLocRequest() { MaterialId = stock.MatId, MaterialCode = stock.MatCode, TunnelNum = reqEntity.TunnelNum, WarehuoseId = warehouse.Id, IsMove = task.Type == TaskType.TransferDepot, Floor = reqEntity.Floor, Fork = 2, Wind = stock.Wind, IsControlpanel = stock.IsControlpanel, IsTorsChk = stock.IsTorsChk, TorsChkQty = stock.TorsChkQty, ProductTime = stock.ProductTime, Wbgroup = stock.WbGroupCode }, _basewarecellrepository, _basewarehouserepository, _billInvnowrepository, _logger); if (cell2.ResCode != ResponseStatusCodeEnum.Sucess.GetHashCode()) { result.ResCode = cell2.ResCode; result.ResMsg = item + cell2.ResMsg; return result; } try { cell2.ResData.Fork = 2; cell2.ResData.TaskNo = item; _db.BeginTran(); _wcstaskoldrepository.AsUpdateable().SetColumns(p => new WCS_TaskOld() { AddrTo = cell2.ResData.CellNo, Fork = cell2.ResData.Fork }).Where(p => p.Id == item).SplitTable(p => p.Take(2)).ExecuteCommand(); _basewarecellrepository.UpdateModelColumns(p => new BaseWarecell() { StateNum = LocationState.LocationState_StockIn, ContGrpBarCode = "", ContGrpId = 0, EditTime = DateTime.Now }, p => cell2.ResData.CellNo == p.Code); _db.CommitTran(); result.ResData.Add(_mapper.Map(cell2.ResData)); } catch (Exception ex) { _db.RollbackTran(); result.ResCode = ResponseStatusCodeEnum.Fail.GetHashCode(); result.ResMsg = item + ResponseStatusCodeEnum.DataSaveErr.GetDescription() + ex.Message; return result; } continue; } #endregion 处理两个任务都是一货叉情况 var cell1 = ApplyLoc(new ApplyLocRequest() { MaterialId = stock.MatId, MaterialCode = stock.MatCode, TunnelNum = reqEntity.TunnelNum, WarehuoseId = warehouse.Id, IsMove = task.Type == TaskType.TransferDepot, Floor = reqEntity.Floor, Fork = 1, Wind = stock.Wind, IsControlpanel = stock.IsControlpanel, IsTorsChk = stock.IsTorsChk, TorsChkQty = stock.TorsChkQty, ProductTime = stock.ProductTime, Wbgroup = stock.WbGroupCode }, _basewarecellrepository, _basewarehouserepository, _billInvnowrepository, _logger); if (cell1.ResCode != ResponseStatusCodeEnum.Sucess.GetHashCode()) { result.ResCode = cell1.ResCode; result.ResMsg = item + cell1.ResMsg; return result; } try { cell1.ResData.Fork = 1; cell1.ResData.TaskNo = item; code = cell1.ResData.CellNo; _db.BeginTran(); _wcstaskoldrepository.AsUpdateable().SetColumns(p => new WCS_TaskOld() { AddrTo = cell1.ResData.CellNo, Fork = cell1.ResData.Fork }).Where(p => p.Id == item).SplitTable(p => p.Take(2)).ExecuteCommand(); _basewarecellrepository.UpdateModelColumns(p => new BaseWarecell() { StateNum = LocationState.LocationState_StockIn, ContGrpBarCode = "", ContGrpId = 0, EditTime = DateTime.Now }, p => cell1.ResData.CellNo == p.Code); _db.CommitTran(); result.ResData.Add(_mapper.Map(cell1.ResData)); } catch (Exception ex) { _db.RollbackTran(); result.ResCode = ResponseStatusCodeEnum.Fail.GetHashCode(); result.ResMsg = item + ResponseStatusCodeEnum.DataSaveErr.GetDescription() + ex.Message; return result; } } } else { //验证库存 var stock = stocklist.Where(p => p.ContGrpBarCode == wcstask.First().BarCode).First(); if (stock == null) { result.ResCode = ResponseStatusCodeEnum.StockNotExist.GetHashCode(); result.ResMsg = wcstask.First().Id + ResponseStatusCodeEnum.StockNotExist.GetDescription(); return result; } if (!string.IsNullOrEmpty(wcstask.First().AddrTo) && wcstask.First().Fork != 0) { var applyCell = new ApplyStockInLocResponse() { TunnelNum = reqEntity.TunnelNum.ToString(), CellNo = wcstask.First().AddrTo, Row = wcstask.First().AddrTo.Split('-')[0] != null ? int.Parse(wcstask.First().AddrTo.Split('-')[0]) : 0, Colomn = wcstask.First().AddrTo.Split('-')[1] != null ? int.Parse(wcstask.First().AddrTo.Split('-')[1]) : 0, Layer = wcstask.First().AddrTo.Split('-')[2] != null ? int.Parse(wcstask.First().AddrTo.Split('-')[2]) : 0, Fork = wcstask.First().Fork, TaskNo = wcstask.First().Id }; result.ResData.Add(applyCell); return result; } var cell1 = ApplyLoc(new ApplyLocRequest() { MaterialId = stock.MatId, MaterialCode = stock.MatCode, TunnelNum = reqEntity.TunnelNum, WarehuoseId = warehouse.Id, IsMove = wcstask.First().Type == TaskType.TransferDepot, Floor = reqEntity.Floor, Fork = 2, Wind = stock.Wind, IsControlpanel = stock.IsControlpanel, IsTorsChk = stock.IsTorsChk, TorsChkQty = stock.TorsChkQty, ProductTime = stock.ProductTime, Wbgroup = stock.WbGroupCode }, _basewarecellrepository, _basewarehouserepository, _billInvnowrepository, _logger); if (cell1.ResCode != ResponseStatusCodeEnum.Sucess.GetHashCode()) { result.ResCode = cell1.ResCode; result.ResMsg = wcstask.First().Id + cell1.ResMsg; return result; } try { cell1.ResData.TaskNo = wcstask.First().Id; cell1.ResData.Fork = 2; _db.BeginTran(); _wcstaskoldrepository.AsUpdateable().SetColumns(p => new WCS_TaskOld() { AddrTo = cell1.ResData.CellNo, Fork = cell1.ResData.Fork, }).Where(p => p.Id == wcstask.First().Id).SplitTable(p => p.Take(2)).ExecuteCommand(); _basewarecellrepository.UpdateModelColumns(p => new BaseWarecell() { StateNum = LocationState.LocationState_StockIn, ContGrpBarCode = "", ContGrpId = 0, EditTime = DateTime.Now }, p => p.Code == cell1.ResData.CellNo); _db.CommitTran(); result.ResData.Add(_mapper.Map(cell1.ResData)); } catch (Exception ex) { _db.RollbackTran(); result.ResCode = ResponseStatusCodeEnum.Fail.GetHashCode(); result.ResMsg = wcstask.First().Id + ResponseStatusCodeEnum.DataSaveErr.GetDescription() + ex.Message; } } return result; } /// /// 申请移库库位及创建移库任务 /// /// 目标货位 /// 历史任务表 /// 仓库表 /// 库存表 /// 货位表 /// 任务表 /// 任务明细表 /// 数据库链接 /// 日志 /// 映射器 /// 装箱任务锁 /// 申请货位锁 /// public static SRes MoveTask( this string Cell, RepositoryTask _wcstaskoldrepository, Repository _basewarehouserepository, Repository _billInvnowrepository, Repository _basewarecellrepository, RepositoryTask _taskrepository, RepositoryTask _taskdetailrepository, ITenant _db, ILogger _logger, IMapper _mapper, object lockerPalletizingPackTask, object lockerApplyLoc) { lock (lockerPalletizingPackTask) { var res = new SRes() { Memo1 = "1" }; var cellform = _basewarecellrepository.GetFirst(p => p.Code == Cell && p.Depth == 2); if (cellform == null) { res.ResCode = ResponseStatusCodeEnum.WareLocationCodeNotExist.GetHashCode(); res.ResMsg = "该任务所在货位不是二深货位"; res.Memo1 = "1"; return res; } var cellTo = _basewarecellrepository.GetFirst(p => p.Col == cellform.Col && p.Layer == cellform.Layer && p.Shelf == cellform.Shelf && p.Depth == 1 && p.IsStop == 0 && p.Floor == cellform.Floor && p.Tunnel == cellform.Tunnel); if (cellTo == null) { res.ResCode = ResponseStatusCodeEnum.WareLocationCodeNotExist.GetHashCode(); res.ResMsg = Cell + "对应一深位货位被禁用或者不存在"; res.Memo1 = "1"; //1:不允许生成出库任务;2:允许 return res; } lock (lockerApplyLoc) { try { if (cellTo.StateNum == LocationState.LocationState_Empty) { res.Memo1 = "2"; return res; } else if (cellTo.StateNum == LocationState.LocationState_Full) { var stock = _billInvnowrepository.GetFirst(p => p.ContGrpBarCode == cellTo.ContGrpBarCode && p.InvStateCode == InvState.InvEcecState_In.ToString()); if (stock == null) { res.ResCode = WcsContractWcsMoveTaskEnum.失败.GetHashCode(); res.ResMsg = "一深位库存信息异常,没有查到库存信息"; res.Memo1 = "1"; return res; } //库位 var cell = ApplyLoc(new ApplyLocRequest() { IsMove = true, MaterialId = stock.MatId, MaterialCode = stock.MatCode, TunnelNum = cellTo.Tunnel, WarehuoseId = cellTo.WarehouseId, Floor = cellTo.Floor, Fork = 2, Wbgroup = stock.WbGroupCode, Wind = stock.Wind, IsControlpanel = stock.IsControlpanel, IsTorsChk = stock.IsTorsChk, TorsChkQty = stock.TorsChkQty, ProductTime = stock.ProductTime }, _basewarecellrepository, _basewarehouserepository, _billInvnowrepository, _logger); if (string.IsNullOrEmpty(cell.ResData.CellNo)) { res.ResCode = WcsContractWcsMoveTaskEnum.失败.GetHashCode(); res.ResMsg = cell.ResMsg; res.Memo1 = "1"; return res; } if (!_basewarecellrepository.IsAny(p => p.Code == cell.ResData.CellNo && p.Row == cell.ResData.Row && p.Col == cell.ResData.Colomn && p.Layer == cell.ResData.Layer && p.StateNum == LocationState.LocationState_Empty && p.IsStop == 0)) { res.ResCode = WcsContractWcsMoveTaskEnum.失败.GetHashCode(); res.ResMsg = cell.ResData.CellNo + "已被使用"; res.Memo1 = "1"; return res; } if (_wcstaskoldrepository.AsQueryable().Where(p => p.Status < TaskStatus.Finish && (p.Type == TaskType.EnterDepot || p.Type == TaskType.TransferDepot) && p.AddrTo == cell.ResData.CellNo).SplitTable(p => p.Take(2)).Any()) { res.ResCode = WcsContractWcsMoveTaskEnum.失败.GetHashCode(); res.ResMsg = cell.ResData.CellNo + "存在未结束的入库任务或移库任务,不允许使用"; res.Memo1 = "1"; return res; } var wcs = new WCS_TaskInfo() { Type = TaskType.TransferDepot, Status = TaskStatus.NewBuild, Priority = 0, Device = cellTo.SCRel, SrmStation = "", AddrFrom = cellTo.Code, AddrTo = cell.ResData.CellNo, LastInteractionPoint = "", BarCode = stock.ContGrpBarCode, Length = stock.LengthQty, AddTime = DateTime.Now, StartTime = DateTime.Now, DocID = 0, PalletType = 1, ProdLine = 0, AddWho = "wms", WarehouseCode = cellTo.WarehouseCode, Enabled = true, WorkBench = "", Tunnel = cellTo.Tunnel.ToString(), Floor = cellTo.Floor, BusType = CpTaskBusType.TaskBusType_CP_Move.GetDescription() }; _db.BeginTran(); var celltemp = _basewarecellrepository.GetSingle(p => p.Code == cell.ResData.CellNo); if (celltemp.StateNum != LocationState.LocationState_Empty || celltemp.ContGrpId > 0 || !string.IsNullOrEmpty(celltemp.ContGrpBarCode)) { _db.RollbackTran(); res.ResCode = WcsContractWcsMoveTaskEnum.失败.GetHashCode(); res.ResMsg = cell.ResData.CellNo + "已被使用"; res.Memo1 = "1"; _logger.LogInformation("货位状态1:" + celltemp.StateNum + ",code:" + cell.ResData.CellNo); return res; } _logger.LogInformation("货位状态2:" + celltemp.StateNum + ",code:" + cell.ResData.CellNo); var task = _taskrepository.InsertReturnEntity(wcs); _wcstaskoldrepository.InsertableSplitTable(_mapper.Map(task)); var taskdlt = new WCS_TaskDtl() { ID = Guid.NewGuid(), CurPoint = task.AddrFrom, AddTime = DateTime.Now, AddWho = "wms", Enabled = true, ParentTaskCode = task.ID, Desc = task.AddrFrom + "移库至" + task.AddrTo, }; _taskdetailrepository.InsertableSplitTable(taskdlt); _basewarecellrepository.UpdateModelColumns(p => new BaseWarecell() { StateNum = LocationState.LocationState_StockMove, EditTime = DateTime.Now }, p => p.Code == task.AddrFrom); _basewarecellrepository.UpdateModelColumns(p => new BaseWarecell() { StateNum = LocationState.LocationState_StockMove, EditTime = DateTime.Now }, p => p.Code == task.AddrTo); _db.CommitTran(); res.Memo1 = "2"; } else if (cellTo.StateNum == LocationState.LocationState_StockIn) { res.ResCode = ResponseStatusCodeEnum.Fail.GetHashCode(); res.ResMsg = "一升位有入库任务,二升位不允许出库"; res.Memo1 = "1"; return res; } else if (cellTo.StateNum == LocationState.LocationState_StockOut) { res.Memo1 = "2"; return res; } else if (cellTo.StateNum == LocationState.LocationState_StockMove) { res.ResCode = ResponseStatusCodeEnum.Fail.GetHashCode(); res.ResMsg = "一升位有移库任务,二升位不允许出库"; res.Memo1 = "1"; return res; } } catch (Exception ex) { _db.RollbackTran(); _logger.LogInformation("移库任务创建失败" + ex.ToString()); res.ResCode = WcsContractWcsMoveTaskEnum.失败.GetHashCode(); res.ResMsg = WcsContractWcsMoveTaskEnum.失败.GetDescription(); res.Memo1 = "1"; } } return res; } } /// /// 申请货位 /// /// 申请信息 /// 货位表 /// 仓库表 /// 库存表 /// 日志 /// public static SRes ApplyLoc( ApplyLocRequest reqEntity, Repository _basewarecellrepository, Repository _basewarehouserepository, Repository _billInvnowrepository, ILogger _logger) { var result = new SRes() { ResCode = ResponseStatusCodeEnum.Sucess.GetHashCode(), ResMsg = ResponseStatusCodeEnum.Sucess.GetDescription(), ResData = new ApplyStockInLocResponse(), }; //预留货位数量 var emptyLoc = _basewarecellrepository.GetList(p => p.IsStop == 0 && p.StateNum == LocationState.LocationState_Empty && p.TypeNum == LocationType.LocationType_StorageLocation && p.Tunnel == reqEntity.TunnelNum && p.WarehouseId == reqEntity.WarehuoseId && p.Floor == reqEntity.Floor ); //判断是否移库 if (!reqEntity.IsMove && (emptyLoc == null || emptyLoc.Count < 10)) { result.ResCode = ResponseStatusCodeEnum.NotEnoughLocation.GetHashCode(); result.ResMsg = ResponseStatusCodeEnum.NotEnoughLocation.GetDescription(); return result; } var loc1ist = from loct1 in _basewarecellrepository.GetList(loc1 => loc1.IsStop == 0 && loc1.StateNum == LocationState.LocationState_Empty && loc1.TypeNum == LocationType.LocationType_StorageLocation && loc1.Tunnel == reqEntity.TunnelNum && loc1.WarehouseId == reqEntity.WarehuoseId && loc1.Floor == reqEntity.Floor && loc1.Depth == 1).ToList() join loct2 in _basewarecellrepository.GetList(loc2 => loc2.IsStop == 0 && loc2.IsStop == 0 && loc2.Depth == 2 && loc2.StateNum == LocationState.LocationState_Full && loc2.Tunnel == reqEntity.TunnelNum && loc2.Floor == reqEntity.Floor).ToList() on new { loct1.Shelf, loct1.Col, loct1.Layer } equals new { loct2.Shelf, loct2.Col, loct2.Layer } join stock in _billInvnowrepository.GetList(inv => inv.InvStateCode == InvState.InvEcecState_In.ToString() && string.IsNullOrEmpty(inv.PreStock)) on loct2.ContGrpBarCode equals stock.ContGrpBarCode where loct1.Tunnel == reqEntity.TunnelNum && loct1.Floor == reqEntity.Floor select new stocktemp1 { Code = loct1.Code.ToString(), Id = loct1.Id, Row = loct1.Row, Col = loct1.Col, Layer = loct1.Layer, Tunnel = loct1.Tunnel, Floor = loct1.Floor, ContGrpBarCode = loct2.ContGrpBarCode, Shelf = loct2.Shelf, MatCode = stock.MatCode, MatId = stock.MatId, WbGroupCode = stock.WbGroupCode, InDocsNo = stock.InDocsNo, Wind = stock.Wind, IsControlpanel = stock.IsControlpanel, IsTorsChk = stock.IsTorsChk, TorsChkQty = stock.TorsChkQty, ProductTime = stock.ProductTime }; #region 非控制盘、已扭转的控制盘 if (reqEntity.IsControlpanel == false) { if (loc1ist != null && loc1ist.ToList().Where(p => p.MatId == reqEntity.MaterialId && p.Wind == reqEntity.Wind && p.IsControlpanel == reqEntity.IsControlpanel && p.WbGroupCode == reqEntity.Wbgroup && Math.Abs((p.ProductTime - reqEntity.ProductTime).TotalHours) < 1).Any()) { if (reqEntity.Fork == 1) { if (loc1ist.ToList().Where(p => p.MatId == reqEntity.MaterialId && p.Col < 70 && p.Wind == reqEntity.Wind && p.IsControlpanel == reqEntity.IsControlpanel && p.WbGroupCode == reqEntity.Wbgroup && Math.Abs((p.ProductTime - reqEntity.ProductTime).TotalHours) < 1).Any()) { var resloc = loc1ist.ToList().Where(p => p.MatId == reqEntity.MaterialId && p.Col < 70 && p.Wind == reqEntity.Wind && p.IsControlpanel == reqEntity.IsControlpanel && p.WbGroupCode == reqEntity.Wbgroup && Math.Abs((p.ProductTime - reqEntity.ProductTime).TotalHours) < 1).OrderBy(p => p.ProductTime).ThenBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First(); result.ResData.TunnelNum = resloc.Tunnel.ToString(); result.ResData.CellNo = resloc.Code; result.ResData.Row = resloc.Row; result.ResData.Colomn = resloc.Col; result.ResData.Layer = resloc.Layer; _logger.LogInformation("分货位埋点1:" + result.ResData.CellNo); return result; } } else { var resloc = loc1ist.ToList().Where(p => p.MatId == reqEntity.MaterialId && p.Wind == reqEntity.Wind && p.IsControlpanel == reqEntity.IsControlpanel && p.WbGroupCode == reqEntity.Wbgroup && Math.Abs((p.ProductTime - reqEntity.ProductTime).TotalHours) < 1).OrderBy(p => p.ProductTime).ThenBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First(); result.ResData.TunnelNum = resloc.Tunnel.ToString(); result.ResData.CellNo = resloc.Code; result.ResData.Row = resloc.Row; result.ResData.Colomn = resloc.Col; result.ResData.Layer = resloc.Layer; _logger.LogInformation("分货位埋点2:" + result.ResData.CellNo); return result; } } } else { if (reqEntity.IsControlpanel == true && reqEntity.IsTorsChk == true && reqEntity.TorsChkQty > 0) //已扭转完 { //var starttime = reqEntity.ProductTime.Date.AddHours(13); //var endtime = reqEntity.ProductTime.Date.AddDays(1).AddHours(8); if (loc1ist != null && loc1ist.ToList().Where(p => p.MatId == reqEntity.MaterialId && p.Wind == reqEntity.Wind && p.IsControlpanel == reqEntity.IsControlpanel && p.WbGroupCode == reqEntity.Wbgroup && reqEntity.IsTorsChk == p.IsTorsChk && p.TorsChkQty > 0).Any())// && p.ProductTime >= starttime && p.ProductTime <= endtime { if (reqEntity.Fork == 1) { if (loc1ist.ToList().Where(p => p.MatId == reqEntity.MaterialId && p.Col < 70 && p.Wind == reqEntity.Wind && p.IsControlpanel == reqEntity.IsControlpanel && p.WbGroupCode == reqEntity.Wbgroup && reqEntity.IsTorsChk == p.IsTorsChk && p.TorsChkQty > 0).Any())//&& p.ProductTime >= starttime && p.ProductTime <= endtime { var resloc = loc1ist.ToList().Where(p => p.MatId == reqEntity.MaterialId && p.Col < 70 && p.Wind == reqEntity.Wind && p.IsControlpanel == reqEntity.IsControlpanel && p.WbGroupCode == reqEntity.Wbgroup && reqEntity.IsTorsChk == p.IsTorsChk && p.TorsChkQty > 0).OrderBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First();//&& p.ProductTime >= starttime && p.ProductTime <= endtime result.ResData.TunnelNum = resloc.Tunnel.ToString(); result.ResData.CellNo = resloc.Code; result.ResData.Row = resloc.Row; result.ResData.Colomn = resloc.Col; result.ResData.Layer = resloc.Layer; _logger.LogInformation("分货位埋点3:" + result.ResData.CellNo); return result; } } else { var resloc = loc1ist.ToList().Where(p => p.MatId == reqEntity.MaterialId && p.Wind == reqEntity.Wind && p.IsControlpanel == reqEntity.IsControlpanel && p.WbGroupCode == reqEntity.Wbgroup && reqEntity.IsTorsChk == p.IsTorsChk && p.TorsChkQty > 0).OrderBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First();//&& p.ProductTime >= starttime && p.ProductTime <= endtime result.ResData.TunnelNum = resloc.Tunnel.ToString(); result.ResData.CellNo = resloc.Code; result.ResData.Row = resloc.Row; result.ResData.Colomn = resloc.Col; result.ResData.Layer = resloc.Layer; _logger.LogInformation("分货位埋点4:" + result.ResData.CellNo); return result; } } } } #endregion 非控制盘、已扭转的控制盘 //再找二深位空的 if (emptyLoc.Where(p => p.Depth == 2).Any()) { //一深位必须空 var templist = from loc1 in _basewarecellrepository.GetList(p => p.Depth == 1 && p.StateNum == LocationState.LocationState_Empty && p.IsStop == 0 && p.Floor == reqEntity.Floor && p.Tunnel == reqEntity.TunnelNum) join loc2 in emptyLoc.Where(p => p.Depth == 2) on new { loc1.Col, loc1.Layer } equals new { loc2.Col, loc2.Layer } select loc2; if (templist == null || !templist.Any()) { result.ResCode = ResponseStatusCodeEnum.NotEnoughLocation.GetHashCode(); result.ResMsg = ResponseStatusCodeEnum.NotEnoughLocation.GetDescription() + "没有可用的二升位"; _logger.LogInformation("分货位埋点5:" + result.ResData.CellNo); return result; } if (!string.IsNullOrEmpty(reqEntity.CellCode)) { var cell = reqEntity.CellCode.Split('-'); if (cell[4] == "2") { var cell2 = templist.Where(p => p.Depth == 2 && p.Shelf == cell[3]).OrderBy(p => p.Layer).ThenBy(p => p.Col).ThenBy(p => p.Row); //优先同货架相邻同层货位 if (cell2.Where(p => p.Depth == 2 && p.Shelf == cell[3] && p.Layer == int.Parse(cell[2])).Any()) { var cell3 = templist.Where(p => p.Depth == 2 && p.Shelf == cell[3] && p.Layer == int.Parse(cell[2])).OrderBy(p => p.Col).ThenBy(p => p.Row).First(); result.ResData.TunnelNum = cell3.Tunnel.ToString(); result.ResData.CellNo = cell3.Code; result.ResData.Row = cell3.Row; result.ResData.Colomn = cell3.Col; result.ResData.Layer = cell3.Layer; result.ResData.Fork = 2; _logger.LogInformation("分货位埋点6:" + result.ResData.CellNo); return result; } else { if (cell2.Any()) { var cell4 = cell2.First(); result.ResData.TunnelNum = cell4.Tunnel.ToString(); result.ResData.CellNo = cell4.Code; result.ResData.Row = cell4.Row; result.ResData.Colomn = cell4.Col; result.ResData.Layer = cell4.Layer; result.ResData.Fork = 2; _logger.LogInformation("分货位埋点7:" + result.ResData.CellNo); return result; } else { var cell4 = templist.OrderBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First(); result.ResData.TunnelNum = cell4.Tunnel.ToString(); result.ResData.CellNo = cell4.Code; result.ResData.Row = cell4.Row; result.ResData.Colomn = cell4.Col; result.ResData.Layer = cell4.Layer; result.ResData.Fork = 2; _logger.LogInformation("分货位埋点8:" + result.ResData.CellNo); return result; } } } } if (reqEntity.Fork == 2) { //var resloc = templist.Where(p => p.Depth == 2).OrderBy(p => p.Layer).ThenBy(p => p.Col).ThenBy(p => p.Row).First(); var resloc = templist.Where(p => p.Depth == 2).OrderBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First(); result.ResData.TunnelNum = resloc.Tunnel.ToString(); result.ResData.CellNo = resloc.Code; result.ResData.Row = resloc.Row; result.ResData.Colomn = resloc.Col; result.ResData.Layer = resloc.Layer; _logger.LogInformation("分货位埋点9:" + result.ResData.CellNo); return result; } else { //templist.Where(p => p.Depth == 2 && p.Col < 70).OrderBy(p => p.Layer).ThenBy(p => p.Col).ThenBy(p => p.Row).Any() if (templist.Where(p => p.Depth == 2 && p.Col < 70).OrderBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).Any()) { //var resloc = templist.Where(p => p.Depth == 2 && p.Col < 70).OrderBy(p => p.Layer).ThenBy(p => p.Col).ThenBy(p => p.Row).First(); var resloc = templist.Where(p => p.Depth == 2 && p.Col < 70).OrderBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First(); result.ResData.TunnelNum = resloc.Tunnel.ToString(); result.ResData.CellNo = resloc.Code; result.ResData.Row = resloc.Row; result.ResData.Colomn = resloc.Col; result.ResData.Layer = resloc.Layer; _logger.LogInformation("分货位埋点10:" + result.ResData.CellNo); return result; } else { } } } if (loc1ist == null || !loc1ist.Any()) { result.ResCode = ResponseStatusCodeEnum.NotEnoughLocation.GetHashCode(); result.ResMsg = ResponseStatusCodeEnum.NotEnoughLocation.GetDescription() + "没有可用的一升位货位"; _logger.LogInformation("分货位埋点11:" + result.ResData.CellNo); return result; } if (reqEntity.Fork == 1) { if (loc1ist.ToList().Where(p => p.Col < 70).Any()) { var aa = loc1ist.ToList(); var code = aa.Where(p => p.Col < 70).OrderBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First(); result.ResData.TunnelNum = code.Tunnel.ToString(); result.ResData.CellNo = code.Code; result.ResData.Row = code.Row; result.ResData.Colomn = code.Col; result.ResData.Layer = code.Layer; _logger.LogInformation("分货位埋点12:" + result.ResData.CellNo); return result; } else { result.ResCode = ResponseStatusCodeEnum.NotEnoughLocation.GetHashCode(); result.ResMsg = "一货叉没有可用库位"; _logger.LogInformation("分货位埋点13:" + result.ResData.CellNo); return result; } } var loc1ist11 = from loct1 in _basewarecellrepository.GetList(loc1 => loc1.IsStop == 0 && loc1.StateNum == LocationState.LocationState_Empty && loc1.TypeNum == LocationType.LocationType_StorageLocation && loc1.Tunnel == reqEntity.TunnelNum && loc1.WarehouseId == reqEntity.WarehuoseId && loc1.Floor == reqEntity.Floor && loc1.Depth == 1 && loc1.Floor == reqEntity.Floor).ToList() join loct2 in _basewarecellrepository.GetList(loc2 => loc2.IsStop == 0 && loc2.Depth == 2 && loc2.StateNum == LocationState.LocationState_Full && loc2.Tunnel == reqEntity.TunnelNum && loc2.Floor == reqEntity.Floor ).ToList() on new { loct1.Shelf, loct1.Col, loct1.Layer } equals new { loct2.Shelf, loct2.Col, loct2.Layer } select loct1; var loc = loc1ist11.ToList().OrderBy(p => p.Col).ThenBy(p => p.Layer).ThenBy(p => p.Row).First(); //var loc = loc1ist.First(); result.ResData.TunnelNum = loc.Tunnel.ToString(); result.ResData.CellNo = loc.Code; result.ResData.Row = loc.Row; result.ResData.Colomn = loc.Col; result.ResData.Layer = loc.Layer; _logger.LogInformation("分货位埋点14:" + result.ResData.CellNo); return result; } #endregion 分配货位 /// /// 码垛工位与对应的机器人的关系 /// /// /// public static string DetermineRoot(string palletequip) { return palletequip switch { "8090" => "Robot1", "8092" => "Robot1", "8096" => "Robot2", "8098" => "Robot2", "8307" => "Robot3", "5434" => "Robot10", _ => string.Empty // 默认值或其他处理 }; } /// /// 创建码垛任务 /// /// /// /// /// /// /// /// /// /// /// /// public static SRes PalletizingPackTask( PalletizingPackTaskRequest request, Repository _wareCell, Repository _invNow, Repository _invFlow, RepositoryTask _task, RepositoryTask _wcsTaskOld, RepositoryTask _taskDetail, ITenant _db, IMapper _mapper, object lockerPalletizingPackTask) { lock (lockerPalletizingPackTask) { var res = new SRes(); try { var wcs = new WCS_TaskInfo() { Status = TaskStatus.NewBuild, Type = TaskType.OutDepot, Priority = 0, Device = request.Srm, SrmStation = request.Srm, AddrFrom = request.CellCode, BarCode = request.Code, AddWho = "wms", EditWho = "wms", WarehouseCode = "sxhouse", AddrTo = request.Equip, FullQty = 1, AgvTaskID = request.PalletLayer, //层配层数 Tunnel = request.Tunnel, MaterialCode = request.Mater, MatCode = request.Mater, OutType = OutTypeEnum.自动出库任务, BusType = SxTaskBusType.TaskBusType_SX_StackStockOut.GetDescription(), Floor = request.Floor, Grade = request.Grade, WorkBench = request.ProductMachCode, PalletizingId = request.PalletizingId, Robot = request.Robot, GoodsType = request.GoodsType, ManualRemarks = request.Memo, DocID = request.DocId }; _db.BeginTran(); _invNow.UpdateSetColumnsTrue(p => new BillInvnow() { InvStateCode = InvState.InvEcecState_OutGoing.ToString(), EditTime = DateTime.Now }, p => p.ContGrpBarCode == request.Code); _wareCell.UpdateSetColumnsTrue(p => new BaseWarecell() { StateNum = LocationState.LocationState_StockOut, EditTime = DateTime.Now }, p => p.Code == request.CellCode); var stock = _invNow.GetSingle(p => p.ContGrpBarCode == request.Code); var flow = _mapper.Map(stock); flow.Id = GetId(); flow.AddTime = DateTime.Now; flow.EditTime = DateTime.Now; flow.InvStateCode = InvState.InvEcecState_OutGoing.ToString(); flow.Memo = "装箱码垛出库"; _invFlow.Insert(flow); var wcstask = _task.InsertReturnEntity(wcs); _wcsTaskOld.InsertableSplitTable(_mapper.Map(wcstask)); var wcsdtl = new WCS_TaskDtl() { ID = Guid.NewGuid(), CurPoint = request.Code, AddTime = DateTime.Now, AddWho = "wms", Enabled = true, ParentTaskCode = wcstask.ID, Desc = wcstask.BusType }; _taskDetail.InsertableSplitTable(wcsdtl); _db.CommitTran(); } catch (Exception ex) { _db.RollbackTran(); res.ResCode = ResponseStatusCodeEnum.Fail.GetHashCode(); res.ResMsg = ResponseStatusCodeEnum.DataSaveErr.GetDescription(); return res; } return res; } } /// /// 获取ID /// /// public static long GetId() { return IdFactory.NewId(); } } }