using HH.WCS.NongFuChaYuan.OtherService; using HH.WCS.NongFuChaYuan.TaskController; using Newtonsoft.Json; using NLog.Fluent; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using static System.Runtime.CompilerServices.RuntimeHelpers; namespace HH.WCS.NongFuChaYuan.WmsService { /// /// 密集型库区 /// internal class IntensiveArea { static IntensiveArea() { //InitRowLockTable(new List { "PGKQ", "PGKTK" }); } /// /// 根据库区和物料获取入库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在) /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// public static Location GetLocation4In(string area, string itemCode, string itemBatch, int standardCarryQty = 1) { Location result = null; try { //1.0 获取每一排最大的列 //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除 var listMaxCol = new SqlHelper().GetInstance().Queryable().Where(a => a.S_AREA_CODE == area).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); //1.1 查到所有有容器的排 var db = new SqlHelper().GetInstance(); var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); if (list.Count > 0) { for (int i = list.Count - 1; i >= 0; i--) { //排除已经锁定的货位 和 放满了且是最大列的货位 //其它项目还需要查询排锁 if (list[i].S_LOCK_STATE.Trim() != "无" || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_LOC_CODE == list[i].S_LOC_CODE) > 0)) { list.Remove(list[i]); } } if (list.Count > 0) { //1.21 加载货位的容器信息 (mapper之前只能是查询原始数据,如果有其他查询 mapper失效) #region MyRegion /* //Console.WriteLine("加载货位的容器信息"); db.ThenMapper(list, loc => { loc.LocCntrRel = db.Queryable().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault(); }); //1.22 加载容器的物料信息 //Console.WriteLine("加载容器的物料信息"); db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => { lcr.CntrItemRel = db.Queryable().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault(); }); */ #endregion //1.3 遍历判断物料类型是否相同 for (int i = 0; i < list.Count; i++) { //todo 还需要判断锁 #region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空 if (list[i].LocCntrRel != null) { //LogHelper.Info("itemCode=" + itemCode); if ((itemCode != null && list[i].LocCntrRel.CntrItemRel != null && list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE.Trim() == itemCode && list[i].LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == itemBatch.Trim()) || (itemCode == null && list[i].LocCntrRel.CntrItemRel == null)) { if (list[i].N_CURRENT_NUM < list[i].N_CAPACITY) { //1.31 如果搬运数量=1 //1.32 搬运多个容器,例如3+3模式 ,必须当前数量=0或3;如果是3+3+,必须当前数量=0或3或6 if (list[i].N_CURRENT_NUM % standardCarryQty == 0) { result = list[i]; } else { //1.33 不满足则选择后一列,后一列肯定是空货位 result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).OrderBy(a => a.N_COL).First(); } } else { //当前货位满了,比他col大一位的货位,后一列肯定是空货位 result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).OrderBy(a => a.N_COL).First(); } if (result != null) { break; } } } else { LogHelper.Info("货位容器物料信息为空"); } #endregion } } } if (result == null) { //todo 还需要判断锁 #region 查找所有数量是空的排 //2.0 简化查询只查每一排第一列 list = db.Queryable().Where(a => a.S_AREA_CODE == area).OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList(); //2.1 选一个空排 for (int i = 0; i < list.Count; i++) { if (list[i].S_LOCK_STATE.Trim() == "无") { //二次校验当前排所有货位都是空的,防止系统数据错乱 var rowSumInfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW).Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First(); if (rowSumInfo.sum == 0) { result = list[i]; break; } } } #endregion } } catch (Exception ex) { //Console.WriteLine("GetLocation4In:" + ex.Message + ex.StackTrace); LogHelper.Error("GetLocation4In:" + ex.Message, ex); } return result; } internal static bool GetYiKuLocation(List rowlist, WorkOrder WorkOrder, string BatchNo) { bool result = false; string startbit = ""; string endbit = ""; string itemcode = ""; string batchNo = ""; int startley = 1; int endley = 1; var dic = new Dictionary(); var strList = new List(); //var intList = new List(); var db = new SqlHelper().GetInstance(); for (int i = 0; i < rowlist.Count(); i++) { string rowNo = rowlist[i]; var rowSum = db.Queryable().Where(a => a.N_ROW == rowNo && a.S_LOCK_STATE.Trim() != "报废").Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First(); dic.Add(rowNo, rowSum.sum); strList.Add(rowNo); } LogHelper.Info($"将所有的排数量放进列表进行排序 各个排数量为{JsonConvert.SerializeObject(dic)}", "自动移库"); for (int i = 0; i < strList.Count() - 1; i++) { for (int j = i + 1; j < strList.Count(); j++) { int ts1 = 0; int ts2 = 0; dic.TryGetValue(strList[i], out ts1); dic.TryGetValue(strList[j], out ts2); if (ts1 > ts2) { string temp = strList[i]; strList[i] = strList[j]; strList[j] = temp; } } } //LogHelper.Info($"排序后的数量为 {JsonConvert.SerializeObject(intList)}"); //for (int i = 0; i < intList.Count(); i++) //{ // string ts = ""; // dic.TryGetValue(intList[i], out ts); // strList.Add(ts); //} LogHelper.Info($"通过数量将排提取出来 排号排序为{JsonConvert.SerializeObject(strList)}"); for (int i = 0; i < strList.Count(); i++) { string startrowNo = strList[i]; var start = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.N_ROW == startrowNo).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).First(); LogHelper.Info($"判断起点 起点货位编码={start.S_LOC_CODE} 物料编码={start.LocCntrRel.CntrItemRel.S_ITEM_CODE} 批次号={start.LocCntrRel.CntrItemRel.S_BATCH_NO}", "自动移库"); for (int j = strList.Count() - 1; j > i; j--) { string endrow = strList[j]; var end = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.N_ROW == endrow).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).First(); LogHelper.Info($"判断终点 终点货位编码={end.S_LOC_CODE} 物料编码={end.LocCntrRel.CntrItemRel.S_ITEM_CODE} 批次号={end.LocCntrRel.CntrItemRel.S_BATCH_NO}", "自动移库"); if (start.LocCntrRel.CntrItemRel.S_ITEM_CODE == end.LocCntrRel.CntrItemRel.S_ITEM_CODE && start.LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == BatchNo && end.LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == BatchNo) { itemcode = start.LocCntrRel.CntrItemRel.S_ITEM_CODE; batchNo = start.LocCntrRel.CntrItemRel.S_BATCH_NO; //物料编码一样的时候确认起点终点 if (end.N_CURRENT_NUM == end.N_CAPACITY) { //如果终点层放满二层 选下一列 end = db.Queryable().Where(a => a.N_ROW == end.N_ROW && a.N_COL == end.N_COL + 1).First(); } } else LogHelper.Info($"物料编码不同 或批次号异常", "自动移库"); } if (!string.IsNullOrEmpty(startbit) && !string.IsNullOrEmpty(endbit)) { break; } } if (result) { //创建任务 var cntrList = LocationHelper.GetLocCntrRel(startbit); if (cntrList.Count > 0) { var trayInfo = new List(); string cntrs = ""; trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(2).ToList();//双托出库 trayInfo.ForEach(a => { cntrs = cntrs + "," + a.S_CNTR_CODE.Trim(); }); var item = db.Queryable().Where(a => a.S_CNTR_CODE == cntrs.Split(',')[0]).First(); if (item != null) { LogHelper.Info($"获取物料配置 物料={item.S_ITEM_CODE} 层数={item.S_ITEM_MODEL}", "自动移库"); var iteminfo = WCSHelper.GetItemrel(item.S_ITEM_CODE, item.S_ITEM_MODEL); DaMingShanCreateTransport(startbit, endbit, WorkOrder.S_ORDER_TYPE, cntrs, startley, endley, WorkOrder.S_PLineNo, 1, 1, int.Parse(iteminfo.S_ITEM_LAYER), WorkOrder.S_WorkNo, batchNo, itemcode); } } else { LogHelper.Info($"获取托盘异常 自动移库获取不到起点托盘 货位编码={startbit}", "自动移库"); } } return result; } /// /// 大明山自动移库 剔除所有满排和空排 /// /// internal static void ExcludeFullEmyRow(ref List rowlist, string S_PLineNo) { var db = new SqlHelper().GetInstance(); for (int i = 0; i < rowlist.Count; i++) { string rowNo = rowlist[i]; var rowSum = db.Queryable().Where(a => a.N_ROW == rowNo && a.S_LOCK_STATE.Trim() != "报废").Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First(); var MaxrowSum = db.Queryable().Where(a => a.N_ROW == rowNo && a.S_LOCK_STATE.Trim() != "报废").Select(a => new { sum = SqlFunc.AggregateSum(a.N_CAPACITY) }).First(); if (rowSum.sum == 0 || rowSum.sum == MaxrowSum.sum) { //解锁 UnlockYiKu(rowNo); rowlist.Remove(rowNo); db.Deleteable().Where(a => a.DeviceName == S_PLineNo && a.RowNo == rowNo).ExecuteCommand(); } } } internal static void ExcludeTaskRow(ref List rowlist) { var db = new SqlHelper().GetInstance(); } internal static void UnlockYiKu(string rowNo) { var db = new SqlHelper().GetInstance(); var lockinfo = db.Queryable().Where(a => a.N_ROW.Trim() == rowNo && a.S_LOCK_STATE.Trim() == "移库锁").ToList(); if (lockinfo.Count > 0) { foreach (var item in lockinfo) { item.S_LOCK_STATE = "无"; db.Updateable(item).UpdateColumns(ab => new { ab.S_LOCK_STATE }).ExecuteCommand(); } TaskProcess.AreaRowLockState(rowNo, false); } } internal static void LockYiKu(ref List rowlist) { var db = new SqlHelper().GetInstance(); for (int i = 0; i < rowlist.Count(); i++) { string rowNo = rowlist[i]; var lockinfo = db.Queryable().Where(a => a.N_ROW.Trim() == rowNo && a.S_LOCK_STATE.Trim() != "移库锁" && a.S_LOCK_STATE.Trim() != "报废" && a.S_LOCK_STATE.Trim() != "无").First(); if (lockinfo == null) { //如果没有移库锁需锁定整排货位 var YikuLockinfo = db.Queryable().Where(a => a.N_ROW.Trim() == rowNo && a.S_LOCK_STATE.Trim() == "移库锁").ToList(); if (YikuLockinfo.Count == 0) { //锁定该排 var rowinfo = db.Queryable().Where(a => a.N_ROW.Trim() == rowNo).ToList(); foreach (var item in rowinfo) { if (item.S_LOCK_STATE.Trim() != "报废") { item.S_LOCK_STATE = "移库锁"; db.Updateable(item).UpdateColumns(ab => new { ab.S_LOCK_STATE }).ExecuteCommand(); } } TaskProcess.AreaRowLockState(rowNo); } } else { rowlist.Remove(rowNo); } } } /// /// 判断任务表是否存在当前库区以及当前库位未完成的任务 均取货完成-true 反之-false /// /// /// /// true:作为 起点判断 false:作为终点判断 /// public static bool TaskTakeAreaOver2(List rowlist) { bool result = true; var db = new SqlHelper().GetInstance(); var taskInfo = db.Queryable().Where(a => a.S_TYPE.Trim() == "自动移库" && a.S_B_STATE.Trim() != "完成" && a.S_B_STATE.Trim() != "失败" && a.S_B_STATE.Trim() != "取消").OrderByDescending(a => a.T_CREATE).ToList();//WmsTaskAction if (taskInfo.Count() > 0) { for (int i = 0; i < rowlist.Count; i++) { string RowNo = rowlist[i]; taskInfo.ForEach(it => { //起点属于 查询库位 内;即 判断 此任务是否有取货完成 var locInfo = db.Queryable().Where(a => a.N_ROW == RowNo && (a.S_LOC_CODE == it.S_START_LOC.Trim() || a.S_LOC_CODE == it.S_END_LOC.Trim())).First(); if (locInfo != null) { result = false; } }); } } return result; } /// /// 根据库区和物料获取出库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在) /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// /// public static Location GetLocation4Out(string area, string itemCode, string itemBatch, int standardCarryQty = 1) { //Console.WriteLine($"area={area}"); Location result = null; var db = new SqlHelper().GetInstance(); //1.0 查到所有有容器的排 var list = db.Queryable().Where(a => a.N_CURRENT_NUM>0).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList(); var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除 if (list.Count > 0) { //LogHelper.Info("GetLocation4Out:" + JsonConvert.SerializeObject(list)); #region MyRegion /* //1.21 加载货位的容器信息 db.ThenMapper(list, loc => { loc.LocCntrRel = db.Queryable().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault(); }); //1.22 加载容器的物料信息 db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => { lcr.CntrItemRel = db.Queryable().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault(); }); */ #endregion //1.3 遍历判断物料类型是否相同 for (int i = 0; i < list.Count; i++) { //todo 还需要判断锁 #region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空 if (list[i].S_LOCK_STATE.Trim() == "无" && list[i].LocCntrRel != null) { if ((itemCode != null && list[i].LocCntrRel.CntrItemRel != null && list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE.Trim() == itemCode && (itemBatch == null || list[i].LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == itemBatch.Trim())) || (itemCode == null && list[i].LocCntrRel.CntrItemRel == null)) { //搬运选择货位 //如果当前出库位后面有空位,不能是入库中 var after = new SqlHelper().Get(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL == list[i].N_COL + 1); if (after == null || after.S_LOCK_STATE.Trim() == "无") { result = list[i]; } if (result != null) { break; } } } #endregion } } return result; } /// /// 初始化密集排锁表格 /// public static void InitRowLockTable(List areas) { var db = new SqlHelper().GetInstance(); var listRowLocks = db.Queryable().ToList(); areas.ForEach(a => { var list = db.Queryable().Where(l => l.S_AREA_CODE == a).Distinct().Select(it => it.N_ROW).ToList(); list.ForEach(r => { if (listRowLocks.Count(d => d.S_AREA_CODE.Trim() == a && d.N_ROW == r) == 0) { var res = db.Insertable(new RowLock { N_ROW = r, S_AREA_CODE = a, S_LOCK_STATE = "无", S_LOCK_SRC = "", S_WORK_MODE = "正常" }).ExecuteCommand(); } }); }); } internal static void Test() { //UnLockLoc("PGKQ-02-02"); //LockLoc("PGKQ-02-02", "入库锁"); //Binding("PGKQ-02-03", "AAA", "", 3); //UnBinding("PGKQ-02-03", 2); //var full = GetLocation4In("PGKQ", "AAA"); //var empty = GetLocation4In("PGKQ", null); //var fullOut = GetLocation4Out("PGKQ", "AAA"); //var emptyOut = GetLocation4Out("PGKQ", null); //var Locations = new SqlHelper().GetList(); //var LocCntrRels = new SqlHelper().GetList(); //var CntrItemRels = new SqlHelper().GetList(); //var list = new SqlHelper().GetInstance().Queryable().LeftJoin((l, lc) => l.S_LOC_CODE == lc.S_LOC_CODE).ToList(); //var results = context.Client.Queryable().Mapper(t=>t.Person, p=>p.PersonId).ToList(); var db = new SqlHelper().GetInstance(); //var list = db.Queryable().Mapper(l => l.LocCntrRel, lcr => lcr.S_LOC_CODE).Where(a=>a.S_LOC_CODE== "PGKQ-01-01").ToList(); //多级查询会嵌套,需要指定导航属性和主键,循环嵌套查询不建议 //[Navigate(NavigateType.OneToOne, nameof(S_LOC_CODE))]、 [Navigate(NavigateType.OneToOne, nameof(S_CNTR_CODE))]、[SugarColumn(IsPrimaryKey = true)] var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList(); #region MyRegion /* // SetContext不会生成循环操作,高性能 和直接Where性能是不一样的 var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0).ToList(); //第一层 db.ThenMapper(list, loc => { loc.LocCntrRel = db.Queryable().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault(); }); //第二层 db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => { lcr.CntrItemRel = db.Queryable().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault(); }); */ #endregion } #region 淳安出入库算法 /// /// 移库出入库处理 /// /// /// /// /// /// /// /// /// /// internal static bool DaMingShanYiKuTask(string startArea, string endArea, string startRow, string endRow, string taskType, string itemCode = "", string batchNo = "", string itemLayer = "", string workNo = "") { var db = new SqlHelper().GetInstance(); bool result = false; var endLocation = new Location(); try { var startLocation = GetYiKuLocationOut(startArea, startRow, itemCode, batchNo, itemLayer); if (startLocation != null && !string.IsNullOrEmpty(startLocation.S_LOC_CODE)) endLocation = GetYiKuLocationIn(endArea, endRow, itemCode, batchNo, 1, itemLayer, startLocation.S_LOC_CODE.Trim()); //else //Console.WriteLine($"{workNo}:移库处理异常:未获取到出库起点信息!"); if (startLocation != null && endLocation != null && startLocation.S_LOCK_STATE.Trim() == "移库锁" && endLocation.S_LOCK_STATE.Trim() == "移库锁") { LogHelper.Info($"人工移库 算法结束获取点位成功"); var startLayer = startLocation.N_CURRENT_NUM; var endLayer = endLocation.N_CURRENT_NUM + 1; var taskNo = DateTime.Now.Ticks.ToString(); //出库要从起点获取托盘 var cntrList = LocationHelper.GetLocCntrRel(startLocation.S_LOC_CODE.Trim()); LogHelper.Info($"人工移库 获取托盘数量={cntrList.Count()}"); //淳安两个托盘为 一个 货位当前容量 if (cntrList.Count > 0) { var trayInfo = new List(); string cntrs = ""; if (cntrList.Count % 2 == 0) trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(2).ToList();//双托出库 else trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(1).ToList();//单托出库 trayInfo.ForEach(a => { cntrs = cntrs + "," + a.S_CNTR_CODE.Trim(); }); var cntr = trayInfo[0].S_CNTR_CODE; var iteminfo = db.Queryable().Where(a => a.S_CNTR_CODE == cntr).First(); if (iteminfo != null) { var cntrtype = db.Queryable().Where(a => a.S_AREA_CODE == startArea).First(); var info = db.Queryable().Where(a => a.S_ITEM_CODE == iteminfo.S_ITEM_CODE && a.S_ITEM_MODEL == iteminfo.S_ITEM_MODEL).First(); result = DaMingShanCreateTransport(startLocation.S_LOC_CODE, endLocation.S_LOC_CODE, taskType, cntrs, startLayer, endLayer, cntrList[0].S_SRC, 1, 1, int.Parse(info.S_ITEM_LAYER), workNo, batchNo, itemCode, cntrtype.S_TRAY_TYPE); } } else { //Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】"); LogHelper.Info($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】", "WMSAlgoRithm"); } } else { string lockStart = ""; string lockEnd = ""; string lockTaskNo = ""; if (startLocation != null && startLocation.S_LOCK_STATE.Trim() != "无") lockStart = startLocation.N_ROW.Trim(); if (endLocation != null && endLocation.S_LOCK_STATE.Trim() != "无") lockEnd = endLocation.N_ROW.Trim(); //var db = new SqlHelper().GetInstance(); if (!string.IsNullOrEmpty(lockStart)) { var taskInfo = db.Queryable().Where(a => (a.S_START_LOC == lockStart || a.S_END_LOC == lockStart) && a.S_B_STATE != "完成" && a.S_B_STATE != "取消" && a.S_B_STATE != "失败").OrderByDescending(a => a.T_CREATE).First(); if (taskInfo != null) lockTaskNo = lockTaskNo + taskInfo.S_TASK_NO.Trim() + ","; } if (!string.IsNullOrEmpty(lockEnd)) { var taskInfo = db.Queryable().Where(a => (a.S_START_LOC == lockEnd || a.S_END_LOC == lockEnd) && a.S_B_STATE != "完成" && a.S_B_STATE != "取消" && a.S_B_STATE != "失败").OrderByDescending(a => a.T_CREATE).First(); if (taskInfo != null) lockTaskNo = lockTaskNo + taskInfo.S_TASK_NO.Trim() + ","; } //Console.WriteLine($"{workNo}:移库处理--起点或终点库位被锁定!锁定任务号:{lockTaskNo}"); LogHelper.Info($"{workNo}:移库处理--起点或终点库位被锁定!锁定任务号:{lockTaskNo}", "WMSAlgoRithm"); } } catch (Exception ex) { LogHelper.Info($"人工移库算法异常 异常信息={ex.Message}"); } return result; } /// /// 备货移库出入库处理 /// /// /// /// /// /// /// /// /// /// internal static bool DaMingShanYiKuTask1(string startArea, string endArea, string startRow, string endRow, string taskType, string workNo = "") { string itemcode = ""; bool result = false; var db = new SqlHelper().GetInstance(); var endLocation = new Location(); try { var startLocation = GetYiKuLocationOut(startArea, startRow); if (startLocation != null && !string.IsNullOrEmpty(startLocation.S_LOC_CODE)) { itemcode = LocationHelper.GetCntrItemRel(startLocation.S_LOC_CODE); endLocation = GetYiKuLocationIn1(endArea, endRow, itemcode); } //else //Console.WriteLine($"{workNo}:移库处理异常:未获取到出库起点信息!"); if (startLocation != null && endLocation != null && startLocation.S_LOCK_STATE.Trim() == "移库锁" && endLocation.S_LOCK_STATE.Trim() == "移库锁") { LogHelper.Info($"备货移库 算法结束获取点位成功"); var startLayer = startLocation.N_CURRENT_NUM; var endLayer = endLocation.N_CURRENT_NUM + 1; var taskNo = DateTime.Now.Ticks.ToString(); //出库要从起点获取托盘 var cntrList = LocationHelper.GetLocCntrRel(startLocation.S_LOC_CODE.Trim()); LogHelper.Info($"备货移库 获取托盘数量={cntrList.Count()}"); //淳安两个托盘为 一个 货位当前容量 if (cntrList.Count > 0) { var trayInfo = new List(); string cntrs = ""; if (cntrList.Count % 2 == 0) trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(2).ToList();//双托出库 else trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(1).ToList();//单托出库 trayInfo.ForEach(a => { cntrs = cntrs + "," + a.S_CNTR_CODE.Trim(); }); var iteminfo = db.Queryable().Where(a => a.S_CNTR_CODE == cntrs.Split(',')[0]).First(); if (iteminfo != null) { var info = db.Queryable().Where(a => a.S_ITEM_CODE == iteminfo.S_ITEM_CODE && a.S_ITEM_MODEL == iteminfo.S_ITEM_MODEL).First(); result = DaMingShanCreateTransport(startLocation.S_LOC_CODE, endLocation.S_LOC_CODE, taskType, cntrs, startLayer, endLayer, "", 1, 1, int.Parse(info.S_ITEM_LAYER), workNo, "", itemcode); } } else { //Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】"); LogHelper.Info($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】", "WMSAlgoRithm"); } } else { string lockStart = ""; string lockEnd = ""; string lockTaskNo = ""; if (startLocation != null && startLocation.S_LOCK_STATE.Trim() != "无") lockStart = startLocation.N_ROW.Trim(); if (endLocation != null && endLocation.S_LOCK_STATE.Trim() != "无") lockEnd = endLocation.N_ROW.Trim(); //var db = new SqlHelper().GetInstance(); if (!string.IsNullOrEmpty(lockStart)) { var taskInfo = db.Queryable().Where(a => (a.S_START_LOC == lockStart || a.S_END_LOC == lockStart) && a.S_B_STATE != "完成" && a.S_B_STATE != "取消" && a.S_B_STATE != "失败").OrderByDescending(a => a.T_CREATE).First(); if (taskInfo != null) lockTaskNo = lockTaskNo + taskInfo.S_TASK_NO.Trim() + ","; } if (!string.IsNullOrEmpty(lockEnd)) { var taskInfo = db.Queryable().Where(a => (a.S_START_LOC == lockEnd || a.S_END_LOC == lockEnd) && a.S_B_STATE != "完成" && a.S_B_STATE != "取消" && a.S_B_STATE != "失败").OrderByDescending(a => a.T_CREATE).First(); if (taskInfo != null) lockTaskNo = lockTaskNo + taskInfo.S_TASK_NO.Trim() + ","; } //Console.WriteLine($"{workNo}:移库处理--起点或终点库位被锁定!锁定任务号:{lockTaskNo}"); LogHelper.Info($"{workNo}:移库处理--起点或终点库位被锁定!锁定任务号:{lockTaskNo}", "WMSAlgoRithm"); } } catch (Exception ex) { LogHelper.Info($"备货移库算法异常 异常信息={ex.Message}"); } return result; } /// /// 判断任务表是否存在当前库区以及当前库位未完成的任务 均取货完成-true 反之-false /// /// /// /// true:作为 起点判断 false:作为终点判断 /// public static bool TaskTakeAreaOver(string AreaNo, string RowNo, bool UnStart = true, bool CmWork = true) { bool result = true; var db = new SqlHelper().GetInstance(); if (UnStart) { var taskInfo = db.Queryable().Where(a => a.S_START_LAREA == AreaNo && a.S_B_STATE.Trim() != "完成" && a.S_B_STATE.Trim() != "失败" && a.S_B_STATE.Trim() != "取消").OrderByDescending(a => a.T_CREATE).ToList();//WmsTaskAction if (taskInfo.Count() > 0) { taskInfo.ForEach(it => { //起点属于 查询库位 内;即 判断 此任务是否有取货完成 var locInfo = db.Queryable().Where(a => a.N_ROW == RowNo && a.S_LOC_CODE == it.S_START_LOC.Trim()).First(); if (locInfo != null) { if (CmWork) { //非缠膜移库工单 执行中任务未取货完成 不允许使用当前库位 var taskAction = db.Queryable().Where(a => a.S_ACTION_CODE == "4" && a.S_TASK_NO == it.S_TASK_NO).First(); if (taskAction == null) result = false; } } }); } } else { var taskInfo = db.Queryable().Where(a => a.S_END_LAREA == AreaNo && a.S_B_STATE.Trim() != "完成" && a.S_B_STATE.Trim() != "失败" && a.S_B_STATE.Trim() != "取消").OrderByDescending(a => a.T_CREATE).ToList();//WmsTaskAction taskInfo.ForEach(it => { //终点查询 只有 此库位 有一条 任务未完成,即 返回false,不可使用 var locInfo = db.Queryable().Where(a => a.N_ROW == RowNo && a.S_LOC_CODE == it.S_END_LOC.Trim()).First(); if (locInfo != null) { //Console.WriteLine($"移库任务判断终点库位是否可用:当前任务未完成,任务号:{it.S_TASK_NO.Trim()}"); result = false; } }); } return result; } /// /// 创建搬运任务 /// /// /// /// /// /// /// /// /// /// public static bool ChunAnCreateTransport(string start, string end, string taskType, string cntrs, int startLayer, int endLayer, string deviceName, int trayCarryCount = 1, int priority = 1, int itemLayer = 5, string workNo = "") { var result = false; var taskNo = DateTime.Now.Ticks.ToString(); var res = TaskHelper.CreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, cntrs, trayCarryCount, startLayer, endLayer, itemLayer, workNo); if (res) { result = true; //任务创建成功,起点货位出库锁定,终点货位入库锁定 LocationHelper.LockLoc(start, "出库锁"); LocationHelper.LockLoc(end, "入库锁"); //排锁定 var db = new SqlHelper().GetInstance(); var Sinfo = db.Queryable().Where(a => a.S_LOC_CODE == start).First(); var Einfo = db.Queryable().Where(a => a.S_LOC_CODE == end).First(); if (Sinfo != null && Einfo != null) { string startRow = string.IsNullOrEmpty(Sinfo.N_ROW) ? "" : Sinfo.N_ROW.Trim(); string sArea = string.IsNullOrEmpty(Sinfo.S_AREA_CODE) ? "" : Sinfo.S_AREA_CODE; string endRow = string.IsNullOrEmpty(Einfo.N_ROW) ? "" : Einfo.N_ROW.Trim(); string eArea = string.IsNullOrEmpty(Einfo.S_AREA_CODE) ? "" : Einfo.S_AREA_CODE; LockRow(startRow, endRow, sArea, eArea, taskType); //if (taskType == "成品下线") //{ // //成品下线 任务类型,需要在终点库位标记下线产线,用于 产线工单结束,进行自动移库 // SignRow(deviceName, endRow, eArea); // //成品下线任务生产成功 删除设备下线时间数据 // db.Deleteable().Where(a => a.DeviceName.Trim() == deviceName).ExecuteCommand(); //} } } return result; } /// /// 根据库区和物料获取入库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在) /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// public static Location GetLocationIn(string area, string itemCode, string itemBatch, string deviceName, string itemLayer) { LogHelper.Info($"入库算法开始", "输送线"); Location result = null; var db = new SqlHelper().GetInstance(); try { //var info = Settings.GetDaMingShanItemNameList().Where(a => a.ItemName == itemCode).FirstOrDefault(); var info = db.Queryable().Where(a => a.S_ITEM_CODE == itemCode && a.S_ITEM_MODEL == itemLayer).First(); if (info != null) { LogHelper.Info("获取到物料编码配置文件", "输送线"); //1.0 获取每一排最大的列 //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除 var listMaxCol = new SqlHelper().GetInstance().Queryable().Where(a => a.S_AREA_CODE == area).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); //1.1 查到所有有容器的排 var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).OrderBy(a => a.N_OROW).Take(1).PartitionBy(a => a.N_ROW).ToList(); if (list.Count > 0) { var time = DateTime.Now; for (int i = list.Count - 1; i >= 0; i--) { //排除已经锁定的货位 和 放满了且是最大列的货位 N_CAPACITY-货位最大容量 //排除已锁定的排 var rowInfo = db.Queryable().Where(a => a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE.Trim() != "无" && a.S_LOCK_STATE.Trim() != "报废").ToList(); if (list[i].S_LOCK_STATE.Trim() != "无" || rowInfo.Count() > 0 || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_LOC_CODE.Trim() == list[i].S_LOC_CODE.Trim()) > 0)) { list.Remove(list[i]); } } var sum = DateTime.Now - time; LogHelper.Info($"库区={area}剔除排 使用时间={sum.TotalMilliseconds}"); var time1 = DateTime.Now; if (list.Count > 0) { LogHelper.Info($"有货物的排数量={list.Count}"); //1.3 遍历判断物料类型是否相同 for (int i = 0; i < list.Count; i++) { //todo 还需要判断锁 #region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空 if (list[i].LocCntrRel != null) { LogHelper.Info($"货位容器数据={JsonConvert.SerializeObject(list[i].LocCntrRel)}"); LogHelper.Info($"容器货品数据={JsonConvert.SerializeObject(list[i].LocCntrRel.CntrItemRel)}"); //var oldinfo = db.Queryable().Where(a => a.S_ITEM_CODE == list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE && a.S_ITEM_MODEL == list[i].LocCntrRel.CntrItemRel.S_ITEM_MODEL).First(); LogHelper.Info($"判断物料是否满足条件 Location={list[i].S_LOC_CODE} itemCode=" + itemCode, "输送线"); //此处需要判断当前满托货位批次号与即将下线的批次号是否相同,不同需要再往后查一个货位 //货位-货位托盘-托盘物料(批次号) if ((itemCode != null && list[i].LocCntrRel.CntrItemRel != null)) { LogHelper.Info($"olditemcode={list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE.Trim()}", "输送线"); //相同物料 相同批次 //oldinfo = Settings.GetDaMingShanItemNameList().Where(a => a.ItemName == list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE.Trim()).FirstOrDefault(); //if (oldinfo != null) //{ //LogHelper.Info($"站点{list[i].S_LOC_CODE} 物料配置 物料编码={oldinfo.S_ITEM_CODE} 层数={oldinfo.S_ITEM_MODEL}", "输送线"); //if (oldinfo.Package != info.Package) //{ // return result; //} if (itemCode.Trim() == list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE.Trim() && list[i].LocCntrRel.S_SRC.Trim() == deviceName && list[i].LocCntrRel.CntrItemRel.S_ITEM_MODEL.Trim() == itemLayer.Trim() && list[i].LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == itemBatch.Trim() ) { //if (list[i].LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == itemBatch.Trim()) //{ if (list[i].N_CURRENT_NUM < list[i].N_CAPACITY) { string locCode = list[i].S_LOC_CODE.Trim(); var trayInfo = db.Queryable().Where(a => a.S_LOC_CODE == locCode).ToList(); if (trayInfo.Count() % 2 == 0) { result = list[i]; } else { //1.33 不满足则选择后一列,后一列肯定是空货位 var locinfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).OrderBy(a => a.N_COL).First(); if (locinfo != null) { result = locinfo; } } } else { //当前货位满了,比他col大一位的货位,后一列肯定是空货位 var locinfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).OrderBy(a => a.N_COL).First(); if (locinfo != null) { result = locinfo; } } //} //else //{ // var locinfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > (list[i].N_COL + 1)).OrderBy(a => a.N_COL).First(); // if (locinfo != null) // { // result = locinfo; // } //} if (result != null) break; } } } else LogHelper.Info("货位容器物料信息为空", "输送线"); #endregion } } var sum1 = DateTime.Now - time1; LogHelper.Info($"库区={area}满排算法 使用时间={sum1.TotalMilliseconds}"); } if (result == null) { list = new List(); var time2 = DateTime.Now; //todo 还需要判断锁 #region 查找所有数量是空的排 //2.0 简化查询只查每一排第一列 LogHelper.Info("判断空排是否满足条件", "输送线"); //list = db.Queryable().Where(a => a.S_AREA_CODE == area).OrderBy(a => a.N_COL).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList(); //list = db.Queryable().Where(a => a.S_AREA_CODE == area).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList(); //找出库区所有排 筛选所有数量为空的排放入集合 var emylist = new List(); list = db.Queryable().Where(a => a.S_AREA_CODE == area).OrderBy(a => a.N_OROW).Take(1).PartitionBy(a => a.N_OROW).ToList(); for (int i = 0; i < list.Count(); i++) { var emyinfo = db.Queryable().Where(a => a.N_ROW == list[i].N_ROW).Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First(); if (emyinfo.sum == 0) { emylist.Add(list[i].N_ROW); } } LogHelper.Info($"空排筛选 经过排序的空排顺序={JsonConvert.SerializeObject(emylist)}"); //2.1 选一个空排 //Console.WriteLine($"空排数量为{emylist.Count}"); LogHelper.Info($"空排数量为{emylist.Count} ", "输送线"); for (int i = 0; i < emylist.Count; i++) { LogHelper.Info($"遍历查找排,库区={area} 排号={emylist[i]}", "输送线"); var state = db.Queryable().Where(a => a.N_ROW == emylist[i] && a.S_LOCK_STATE != "无" && a.S_LOCK_STATE != "报废").First(); if (state == null) { var locinfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == emylist[i] && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE == "无").OrderBy(a => a.N_COL).First(); if (locinfo != null) { LogHelper.Info($"货位编码={locinfo.S_LOC_CODE},货位状态={locinfo.S_LOCK_STATE},货位数量={locinfo.N_CURRENT_NUM}", "输送线"); //Console.WriteLine("开启二次校验"); //二次校验当前排所有货位都是空的,防止系统数据错乱 string row = locinfo.N_ROW.Trim(); var rowSumInfo = db.Queryable().Where(a => a.N_ROW == row).Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First(); if (rowSumInfo.sum == 0) { result = locinfo; break; } else { LogHelper.Info($"排{row} 不为空排 当前数量={rowSumInfo.sum}"); } } } #endregion } var sum2 = DateTime.Now - time2; LogHelper.Info($"库区={area}空排算法 使用时间={sum2.TotalMilliseconds}"); } else if (result.S_LOCK_STATE.Trim() != "无") { result = null; } } } catch (Exception ex) { //Console.WriteLine("GetLocationIn:" + ex.Message + ex.StackTrace); LogHelper.Error("GetLocationIn:" + ex.Message, ex); } return result; } /// /// 根据库区和物料获取出库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在) /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// /// public static Location GetLocationOut(string area, string itemCode, string itemBatch, string itemLayer) { //Console.WriteLine($"area={area}"); Location result = null; var db = new SqlHelper().GetInstance(); itemCode = itemCode + itemLayer; //1.0 查到所有有容器的排 var list = db.Queryable().Where(a => a.N_CURRENT_NUM>0).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList(); var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除 if (list.Count > 0) { //1.3 遍历判断物料类型是否相同 for (int i = 0; i < list.Count; i++) { //todo 还需要判断锁 #region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空 if (list[i].S_LOCK_STATE.Trim() == "无" && list[i].LocCntrRel != null) { if ((itemCode != null && list[i].LocCntrRel.CntrItemRel != null && list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE.Trim() == itemCode && (itemBatch == null || list[i].LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == itemBatch.Trim())) || (itemCode == null && list[i].LocCntrRel.CntrItemRel == null)) { //搬运选择货位 //如果当前出库位后面有空位,不能是入库中 string row = list[i].N_ROW.Trim(); int col = list[i].N_COL + 1; var after = new SqlHelper().Get(a => a.S_AREA_CODE == area && a.N_ROW == row && a.N_COL == col); if (after == null || after.S_LOCK_STATE.Trim() == "无") { result = list[i]; } if (result != null) { break; } } } #endregion } } return result; } /// /// 移库获取入库货位 /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// public static Location GetYiKuLocationIn(string area, string row, string itemCode = "", string itemBatch = "", int standardCarryQty = 0, string itemLayer = "", string startLoc = "") { //库区货位约定:列号越小越靠里 Location result = null; Location res = null; //itemCode = itemCode + itemLayer; try { //Console.WriteLine($"移库任务入库计算:当前库区:{area},当前库位:{row}!"); LogHelper.Info($"移库任务入库计算:当前库区:{area},当前库位:{row}!", "WMSAlgoRithm"); var db = new SqlHelper().GetInstance(); //入库 降序 从外往里查,获取 最靠外 的有托盘的货位;判断当前货位 托盘数量是否 满托; //满托获取后面一个货位;反之,使用此货位 var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area && a.N_ROW == row).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).First(); if (list != null) { //获取当前货位所有托盘数 var trayInfo = db.Queryable().Where(a => a.S_LOC_CODE == list.S_LOC_CODE.Trim()).ToList(); //判断前一个货位与当前批次是否一样,不一样需要空一个货位 bool batch = BatchBool(list.S_LOC_CODE.Trim(), startLoc, db); if (trayInfo.Count() == list.N_CAPACITY * 2 || trayInfo.Count() % 2 != 0 || batch) { //1.当前货位满了 查询后面一个货位 必然是空货位 //2.当前货位为 1+2 或 1 的货位,不可再入库,查询后面的货位 //3.不同批次号的物料需要隔一个货位 int Col = list.N_COL + 1; if (batch) Col = Col + 1; res = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == row && a.N_COL == Col).Take(1).First(); result = res; } else { result = list; } } else { LogHelper.Info($"终点库区={area} 排={row}"); var empty = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).OrderBy(a => a.N_COL).Where(a => a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE.Trim() == "移库锁").First(); //2.1 选一个空排 if (empty != null) result = empty; else { //Console.WriteLine($"移库任务入库计算异常:当前库位以及库区无可用货位!当前库区:{area},当前库位:{row}!"); LogHelper.Info($"移库任务入库计算异常:当前库位以及库区无可用货位!当前库区:{area},当前库位:{row}!", "WMSAlgoRithm"); } } } catch (Exception ex) { //Console.WriteLine("GetLocationIn:" + ex.Message + ex.StackTrace); LogHelper.Error("GetLocationIn:" + ex.Message, ex); } if (result != null) LogHelper.Info($"人工移库入库算法 终点货位={result.S_LOC_CODE}"); return result; } /// /// 移库获取入库货位 /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// public static Location GetYiKuLocationIn1(string area, string row, string itemCode = "") { //库区货位约定:列号越小越靠里 Location result = null; Location res = null; //itemCode = itemCode + itemLayer; try { //Console.WriteLine($"移库任务入库计算:当前库区:{area},当前库位:{row}!"); LogHelper.Info($"移库任务入库计算:当前库区:{area},当前库位:{row}!", "WMSAlgoRithm"); var db = new SqlHelper().GetInstance(); //入库 降序 从外往里查,获取 最靠外 的有托盘的货位;判断当前货位 托盘数量是否 满托; //满托获取后面一个货位;反之,使用此货位 var list = db.Queryable().Where(a => a.N_CURRENT_NUM == 0 && a.S_AREA_CODE == area && a.N_ROW == row).OrderBy(a => a.N_COL).First(); if (list != null) { result = list; } else { var empty = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).OrderBy(a => a.N_COL).Where(a => a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE.Trim() == "移库锁").First(); //2.1 选一个空排 if (empty != null) result = empty; else { //Console.WriteLine($"移库任务入库计算异常:当前库位以及库区无可用货位!当前库区:{area},当前库位:{row}!"); LogHelper.Info($"移库任务入库计算异常:当前库位以及库区无可用货位!当前库区:{area},当前库位:{row}!", "WMSAlgoRithm"); } } } catch (Exception ex) { //Console.WriteLine("GetLocationIn:" + ex.Message + ex.StackTrace); LogHelper.Error("GetLocationIn:" + ex.Message, ex); } if (result != null) LogHelper.Info($"人工移库入库算法 终点货位={result.S_LOC_CODE}"); return result; } private static bool BatchBool(string endLoc, string startLoc, SqlSugarClient db) { //Console.WriteLine($"移库入库批次号判断:入库终点货位:{endLoc},出库起点货位:{startLoc}"); bool batch = false; var endCntr = db.Queryable().Where(a => a.S_LOC_CODE == endLoc).First(); var startCntr = db.Queryable().Where(a => a.S_LOC_CODE == startLoc).First(); if (endCntr != null && startCntr != null) { var endItem = db.Queryable().Where(a => a.S_CNTR_CODE == endCntr.S_CNTR_CODE.Trim()).First(); var startItem = db.Queryable().Where(a => a.S_CNTR_CODE == startCntr.S_CNTR_CODE.Trim()).First(); if (endItem != null && startItem != null && !string.IsNullOrEmpty(endItem.S_BATCH_NO)) { if (endItem.S_BATCH_NO.Trim() != startItem.S_BATCH_NO.Trim()) batch = true; } //else //Console.WriteLine($"移库入库批次号判断:起点或终点 托盘物料表 为空!"); } //else //Console.WriteLine($"移库入库批次号判断:起点或终点 托盘货位表 为空!"); return batch; } /// /// 出库获取出库货位 /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// /// public static Location GetYiKuLocationOut(string area, string row, string itemCode = "", string itemBatch = "", string itemLayer = "") { //Console.WriteLine($"移库任务出库计算:当前库区:{area},当前库位:{row}!"); LogHelper.Info($"移库任务出库计算:当前库区:{area},当前库位:{row}!", "WMSAlgoRithm"); Location result = null; var db = new SqlHelper().GetInstance(); //itemCode = itemCode + itemLayer; var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area && a.N_ROW == row).OrderByDescending(a => a.N_COL).Take(1).First(); if (list != null) { result = list; LogHelper.Info($"移库出库算法 起点货位={result.S_LOC_CODE}"); } else { //Console.WriteLine($"移库任务出库计算异常:当前库位以及库区无可用货位!当前库区:{area},当前库位:{row}!"); LogHelper.Info($"移库任务出库计算异常:当前库位以及库区无可用货位!当前库区:{area},当前库位:{row}!", "WMSAlgoRithm"); } return result; } /// /// 出库获取空托出库货位 /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// /// public static Location GetEmptyLocationOut(string area, string row, string trayType) { //Console.WriteLine($"空托任务出库计算:当前库区:{area},当前库位:{row}!"); LogHelper.Info($"空托任务出库计算:当前库区:{area},当前库位:{row}!", "WMSAlgoRithm"); Location result = null; var db = new SqlHelper().GetInstance(); //itemCode = itemCode + itemLayer; var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area && a.N_ROW == row).OrderByDescending(a => a.N_COL).Take(1).First(); if (list != null) { string note = string.IsNullOrEmpty(list.S_NOTE) ? "" : list.S_NOTE.Trim(); if (string.IsNullOrEmpty(note) || note == trayType) result = list; else LogHelper.Info($"空托任务出库计算异常:当前库位与所需托盘类型不一致。当前库区:{area},当前库位:{row}!所需托盘:{trayType},当前托盘:{note}", "WMSAlgoRithm"); } else { //Console.WriteLine($"空托任务出库计算异常:当前库位以及库区无可用货位!当前库区:{area},当前库位:{row}!"); LogHelper.Info($"空托任务出库计算异常:当前库位以及库区无可用货位!当前库区:{area},当前库位:{row}!", "WMSAlgoRithm"); } return result; } /// /// 绑定货位容器表 /// /// /// internal static bool BindLocCntr(string loc, string cntr, string itemCode, string batchNo, string deviceName = "", string itemlayer = "", string ItemTrayType = "") { bool result = true; List list = new List(cntr.Split(',')); var db = new SqlHelper().GetInstance(); list.ForEach(it => { if (!string.IsNullOrEmpty(it)) { string cntrCode = it.Trim(); LogHelper.Info($"查找货位{loc} 是否存在容器{cntrCode}的托盘"); var Cntr = db.Queryable().Where(a => a.S_LOC_CODE == loc && a.S_CNTR_CODE == cntrCode).First(); if (Cntr == null) { LogHelper.Info("容器不存在准备插入"); var cir = new LocCntrRel { S_LOC_CODE = loc, S_CNTR_CODE = cntrCode, S_SRC = deviceName }; db.Insertable(cir).ExecuteCommand(); LogHelper.Info($"容器插入成功"); IntensiveArea.BindCntrItem(cntrCode, itemCode, batchNo, itemlayer); } else { LogHelper.Info("容器已存在"); } } }); //1.0 查货位容器表 return result; } /// /// 绑定容器物料表 /// /// /// /// /// internal static bool BindCntrItem(string trayCode, string itemCode, string batchNo, string itemlayer = "") { LogHelper.Info($"容器货品绑定 容器{trayCode}"); var res = false; var db = new SqlHelper().GetInstance(); try { db.BeginTran(); //db.Updateable(cntr).UpdateColumns(it => new { it.S_DEST }).ExecuteCommand(); //1.将原有容器物料信息删除 //db.Deleteable().Where(it => it.S_CNTR_CODE == cntr.S_CNTR_CODE.Trim()).ExecuteCommand(); //2.插入新的容器物料信息(容器号不变) LogHelper.Info($"查找容器货品绑定表中是否有相同容器号的物料"); var info = db.Queryable().Where(a => a.S_CNTR_CODE == trayCode.Trim()).First(); if (info == null) { LogHelper.Info($"插入容器货品数据"); var cir = new CntrItemRel { S_CNTR_CODE = trayCode, S_BATCH_NO = batchNo, S_ITEM_CODE = itemCode, S_ITEM_MODEL = itemlayer }; db.Insertable(cir).ExecuteCommand(); LogHelper.Info($"插入成功"); } else { LogHelper.Info($"托盘号重复"); } db.Ado.CommitTran(); res = true; } catch (Exception ex) { db.Ado.RollbackTran(); } return res; } /// /// 任务创建时锁定排 /// /// /// public static void LockRow(string startRow, string endRow, string SArea, string EArea, string taskType) { string startRowXB = startRow + ""; string endRowXB = endRow + ""; string SAreaXB = SArea + ""; string EAreaXB = EArea + ""; var db = new SqlHelper().GetInstance(); string LockRow = ""; var Srow = db.Queryable().Where(a => a.N_ROW == startRow && a.S_AREA_CODE == SArea).First(); if (Srow != null && !Srow.S_LOCK_STATE.Trim().Contains("锁")) { Srow.S_LOCK_STATE = "出库锁"; db.Updateable(Srow).UpdateColumns(it => new { it.S_LOCK_STATE }).ExecuteCommand(); LockRow = LockRow + Srow.N_ROW.Trim().Replace("-XB", "") + ","; } var Erow = db.Queryable().Where(a => a.N_ROW == endRow && a.S_AREA_CODE == EArea).First(); if (Erow != null && !Erow.S_LOCK_STATE.Trim().Contains("锁")) { Erow.S_LOCK_STATE = "入库锁"; db.Updateable(Erow).UpdateColumns(it => new { it.S_LOCK_STATE }).ExecuteCommand(); LockRow = LockRow + Erow.N_ROW.Trim().Replace("-XB", "") + ","; } if (!string.IsNullOrEmpty(LockRow) && taskType.Contains("移库")) TaskProcess.AreaRowLockState(LockRow);//移库任务 回报富勒库位锁定 } /// /// 解锁排 /// /// /// public static void UnLockRow(string bit, string taskType) { if (!taskType.Contains("移库")) { string rowNo = ""; string areaCode = ""; var db = new SqlHelper().GetInstance(); var Sinfo = new SqlHelper().GetInstance().Queryable().Where(a => a.S_LOC_CODE == bit).First(); if (Sinfo != null) { rowNo = string.IsNullOrEmpty(Sinfo.N_ROW.Trim()) ? "" : Sinfo.N_ROW.ToString(); areaCode = string.IsNullOrEmpty(Sinfo.S_AREA_CODE.Trim()) ? "" : Sinfo.S_AREA_CODE.Trim(); var listRowLocks = db.Queryable().ToList(); var Srow = db.Queryable().Where(a => a.N_ROW == rowNo && a.S_AREA_CODE == areaCode).First(); if (Srow != null && Srow.S_LOCK_STATE.Trim().Contains("锁")) { Srow.S_LOCK_STATE = "无"; db.Updateable(Srow).UpdateColumns(it => new { it.S_LOCK_STATE }).ExecuteCommand(); //TaskProcess.AreaRowLockState(Srow.N_ROW.Trim(), false);//回报WMS库位锁定信息--暂不使用 } } else LogHelper.Info($"当前货位不存在于货位表,货位编码:{bit}", "WMSAlgoRithm"); } } /// /// 更新工单移库数量 /// /// internal static void UpdateWorkNum(WMSTask mst) { var db = new SqlHelper().GetInstance(); var workInfo = db.Queryable().Where(a => a.S_WorkNo == mst.S_SRC_NO.Trim()).First(); LogHelper.Info($"查询工单号为{mst.S_SRC_NO} 的移库工单"); if (workInfo != null) { LogHelper.Info($"找到移库工单 移库数量为{workInfo.S_YiKuNum}"); if (workInfo.S_YiKuNum != 9999 && workInfo.S_YiKuNum > 0) { workInfo.S_YiKuNum = workInfo.S_YiKuNum - 1; LogHelper.Info($"修改移库数量为{workInfo.S_YiKuNum}"); db.Updateable(workInfo).UpdateColumns(a => new { a.S_YiKuNum }).ExecuteCommand(); } } else { //Console.WriteLine($"更新工单移库数量异常:未查询到此工单的信息,工单号:{mst.S_SRC_NO.Trim()}"); } } #endregion #region 大明山出入库算法 /// /// 注塑机入库 翻斗机入库 /// /// /// 起点 /// 托盘号 /// 批次号 /// true:注塑机入库 false:翻斗机入库 /// public static bool DaMingShanPLCIn(Settings.deviceInfo plc, string location, string trayCode, string batchNo, PGWorkOrder workorder, bool v) { LogHelper.Info($"查询瓶坯满筐入库站点", "注塑机"); string endlocation = ""; var db = new SqlHelper().GetInstance(); bool result = false; //var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == plc.deviceName && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == workorder.S_LinkLineNo && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); if (v) { //即产即用 优先送翻斗机缓存位 if (info != null) { string ItemName = workorder.S_ItemCode; //查询对应终点的库位状态 if (info.ProductLocation.Count() > 0) { LogHelper.Info($"遍历查询缓存点的状态 result={result}", "注塑机"); foreach (var a in info.ProductLocation) { var endlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a && b.N_CURRENT_NUM == 0 && b.S_LOCK_STATE.Trim() == "无").First(); if (endlocationinfo != null) { endlocation = endlocationinfo.S_LOC_CODE.Trim(); result = DaMingShanCreateTransport(location, endlocation, "注塑即产满筐下线(瓶坯)", trayCode, 1, 1, plc.deviceName, 1); break; } } } LogHelper.Info($"遍历缓存点状态结束 result={result}"); //对应终点找不到空闲货位 从对应库区寻找空闲货位 if (!result) { LogHelper.Info($"遍历查询缓存区的状态 缓存区配置={JsonConvert.SerializeObject(info.ProductArea)}", "注塑机"); if (info.IsDense == 0) { for (int i = 0; i < info.ProductArea.Count(); i++) { string endarea = info.ProductArea[i]; LogHelper.Info($"查询满筐缓存位 是否有空货位 库区编码={endarea}"); var endLocation = db.Queryable().Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE.Trim() == "无").First(); if (endLocation != null) { var endLayer = endLocation.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, endLocation.S_LOC_CODE, "注塑即产满筐下线(瓶坯)", trayCode, 1, endLayer, plc.deviceName, 1); break; } } } else { for (int i = 0; i < info.ProductArea.Count(); i++) { string endarea = info.ProductArea[i]; var endbitlist = db.Queryable() .Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE == "无") .PartitionBy(a => a.N_OROW) .Take(1) .OrderBy(a => a.N_COL) .ToList(); foreach (var item in endbitlist) { var lockinfo = db.Queryable().Where(a => a.S_AREA_CODE == item.S_AREA_CODE && a.N_ROW == item.N_ROW && a.S_LOCK_STATE != "无").First(); if (lockinfo == null) { var endLayer = item.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, item.S_LOC_CODE, "注塑即产满筐下线(瓶坯)", trayCode, 1, endLayer, plc.deviceName, 1); break; } } if (result) break; } } } LogHelper.Info($"遍历缓存区状态结束 result={result}"); if (!result) { if (info.IsDense == 0) { var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 3 && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); if (bitinfo != null) { var locinfo = db.Queryable().Where(q => q.S_AREA_CODE == bitinfo.location && q.N_CURRENT_NUM == 0 && q.S_LOCK_STATE.Trim() == "无").First(); if (locinfo != null) { var endLayer = locinfo.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, locinfo.S_LOC_CODE, "注塑即产满筐下线(瓶坯)", trayCode, 1, endLayer, plc.deviceName, 1); } } } } LogHelper.Info($"遍历入库缓存位结束 result={result}"); if (result) { IntensiveArea.BindCntrItem(trayCode, ItemName, batchNo); } } } else { //非即产即用 直接入库缓存位 3+2 var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 3 && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); if (info != null && bitinfo != null) { string ItemName = info.ItemName; var locinfo = db.Queryable().Where(a => a.S_AREA_CODE == bitinfo.location && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE == "无").OrderBy(a => a.N_COL).First(); if (locinfo != null) { var endLayer = locinfo.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, locinfo.S_LOC_CODE, "注塑即产满筐下线(瓶坯)", trayCode, 1, endLayer, plc.deviceName, 1); } if (result) { IntensiveArea.BindCntrItem(trayCode, ItemName, batchNo); } } } return result; } /// /// 瓶盖机入库 /// /// /// 起点 /// 托盘号 /// 批次号 /// true:即产即用 false:非即产即用 /// public static bool DaMingShanPLCIn2(Settings.deviceInfo plc, string location, string trayCode, string batchNo, string itemcode, bool v) { LogHelper.Info($"查询瓶盖满筐入库站点", "瓶盖机"); string endlocation = ""; var db = new SqlHelper().GetInstance(); bool result = false; var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == plc.deviceName && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); if (v) { //即产即用 优先送翻斗机缓存位 if (info != null) { string ItemName = itemcode; //查询对应终点的库位状态 if (info.ProductLocation.Count() > 0) { LogHelper.Info($"遍历查询缓存点的状态", "瓶盖机"); foreach (var a in info.ProductLocation) { var endlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a).First(); if (endlocationinfo.N_CURRENT_NUM == 0 && endlocationinfo.S_LOCK_STATE.Trim() == "无") { endlocation = endlocationinfo.S_LOC_CODE.Trim(); result = DaMingShanCreateTransport(location, endlocation, "注塑即产满筐下线(瓶盖)", trayCode, 1, 1, plc.deviceName, 1); break; } } } //对应终点找不到空闲货位 从对应库区寻找空闲货位 if (!result) { LogHelper.Info($"遍历查询缓存区的状态", "瓶盖机"); string endarea = info.ProductArea[0]; LogHelper.Info($"查询满筐缓存位 是否有空货位 库区编码={endarea}"); var endLocation = db.Queryable().Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM == 0).First(); if (endLocation.S_LOCK_STATE.Trim() == "无") { var endLayer = endLocation.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, endLocation.S_LOC_CODE, "注塑即产满筐下线(瓶盖)", trayCode, 1, endLayer, plc.deviceName, 1); } } if (!result) { var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 1 && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); if (bitinfo != null) { var locinfo = db.Queryable().Where(q => q.S_LOC_CODE == bitinfo.location).First(); if (locinfo != null) { if (locinfo.S_LOCK_STATE == "无") { var endLayer = locinfo.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, locinfo.S_LOC_CODE, "注塑即产满筐下线(瓶盖)", trayCode, 1, endLayer, plc.deviceName, 1); } } } } if (result) { IntensiveArea.BindCntrItem(trayCode, ItemName, batchNo); } } } else { //非即产即用 直接入库缓存位 3+2 var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 1 && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); if (info != null && bitinfo != null) { string ItemName = info.ItemName; var locinfo = db.Queryable().Where(q => q.S_LOC_CODE == bitinfo.location).First(); if (locinfo != null) { if (locinfo.S_LOCK_STATE == "无" && locinfo.N_CURRENT_NUM < locinfo.N_CAPACITY) { var endLayer = locinfo.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, locinfo.S_LOC_CODE, "注塑即产满筐下线(瓶盖)", trayCode, 1, endLayer, plc.deviceName, 1); } } if (result) { IntensiveArea.BindCntrItem(trayCode, ItemName, batchNo); } } } return result; } /// /// 瓶盖翻斗机入库 /// /// /// 起点 /// 托盘号 /// 批次号 /// true:即产即用 false:非即产即用 /// public static bool DaMingShanPLCIn3(Settings.deviceInfo plc, string location, string trayCode, string batchNo, bool v) { LogHelper.Info($"查询瓶盖翻斗机空筐入库站点", "翻斗机"); string endlocation = ""; var db = new SqlHelper().GetInstance(); bool result = false; var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == plc.deviceName && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (v) { //即产即用 优先送翻斗机缓存位 if (info != null) { //查询对应终点的库位状态 if (info.ProductLocation.Count() > 0) { LogHelper.Info($"遍历查询缓存点的状态", "翻斗机"); foreach (var a in info.ProductLocation) { var endlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a).First(); if (endlocationinfo != null) { if (endlocationinfo.N_CURRENT_NUM == 0 && endlocationinfo.S_LOCK_STATE.Trim() == "无") { endlocation = endlocationinfo.S_LOC_CODE.Trim(); result = DaMingShanCreateTransport(location, endlocation, "翻斗机即产空筐下线(瓶盖)", trayCode, 1, 1, plc.deviceName, 1); break; } } } } //对应终点找不到空闲货位 从对应库区寻找空闲货位 if (!result) { LogHelper.Info($"遍历查询缓存区的状态", "翻斗机"); string endarea = info.ProductArea[0]; LogHelper.Info($"查询空筐筐缓存位 是否有空货位 库区编码={endarea}"); var endlocationlist = db.Queryable() .Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM < a.N_CAPACITY) .PartitionBy(a => a.N_ROW) .Take(1) .OrderBy(a => a.N_COL) .OrderBy(a => a.N_OROW) .ToList(); foreach (var item in endlocationlist) { var lockinfo = db.Queryable().Where(a => a.S_AREA_CODE == item.S_AREA_CODE && a.N_ROW == item.N_ROW && a.S_LOCK_STATE != "无").First(); if (lockinfo == null) { var endLayer = item.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, item.S_LOC_CODE, "翻斗机即产空筐下线(瓶盖)", trayCode, 1, endLayer, plc.deviceName, 1); break; } } //var endLocation = db.Queryable().Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM == 0).First(); //if (endLocation.S_LOCK_STATE.Trim() == "无") //{ // //} } if (!result) { var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 2 && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (bitinfo != null) { var endarea = bitinfo.ProductArea[0]; var endbitlist = db.Queryable().Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM == 0) .PartitionBy(a => a.N_ROW) .OrderBy(a => a.N_COL) .Take(1) .ToList(); foreach (var item in endbitlist) { var lockinfo = db.Queryable().Where(a => a.S_AREA_CODE == item.S_AREA_CODE && a.N_ROW == a.N_ROW && a.S_LOCK_STATE != "无").First(); if (lockinfo == null) { var endLayer = item.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, item.S_LOC_CODE, "翻斗机即产空筐下线(瓶盖)", trayCode, 1, endLayer, plc.deviceName, 1); break; } } } } if (result) { IntensiveArea.UnBindLocCntr(trayCode); } } } else { //非即产即用 直接入库缓存位 3+2 var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 2 && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (info != null && bitinfo != null) { //var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 2 && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (bitinfo != null) { var endarea = bitinfo.ProductArea[0]; var endbitlist = db.Queryable().Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM a.N_ROW) .OrderBy(a => a.N_COL) .Take(1) .ToList(); foreach (var item in endbitlist) { var lockinfo = db.Queryable().Where(a => a.S_AREA_CODE == item.S_AREA_CODE && a.N_ROW == a.N_ROW && a.S_LOCK_STATE != "无").First(); if (lockinfo == null) { var endLayer = item.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, item.S_LOC_CODE, "翻斗机即产空筐下线(瓶盖)", trayCode, 1, endLayer, plc.deviceName, 1); break; } } } if (result) { IntensiveArea.UnBindLocCntr(trayCode); } } } return result; } /// /// 瓶坯翻斗机入库 /// /// /// 起点 /// 托盘号 /// 批次号 /// true:即产即用 false:非即产即用 /// public static bool DaMingShanPLCIn4(Settings.deviceInfo plc, string location, string trayCode, PGWorkOrder workorder, bool v) { LogHelper.Info($"查询瓶坯翻斗机空筐入库站点", "翻斗机"); string endlocation = ""; var db = new SqlHelper().GetInstance(); bool result = false; //var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == plc.deviceName && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == workorder.S_LinkLineNo && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (v) { //即产即用 优先送翻斗机缓存位 if (info != null) { //查询对应终点的库位状态 if (info.ProductLocation.Count() > 0) { LogHelper.Info($"遍历查询缓存点的状态", "翻斗机"); foreach (var a in info.ProductLocation) { var endlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a).First(); if (endlocationinfo != null) { if (endlocationinfo.N_CURRENT_NUM == 0 && endlocationinfo.S_LOCK_STATE.Trim() == "无") { endlocation = endlocationinfo.S_LOC_CODE.Trim(); result = DaMingShanCreateTransport(location, endlocation, "翻斗机即产空筐下线(瓶坯)", trayCode, 1, 1, plc.deviceName, 1); break; } } } } //对应终点找不到空闲货位 从对应库区寻找空闲货位 if (!result) { LogHelper.Info($"遍历查询缓存区的状态", "翻斗机"); string endarea = info.ProductArea[0]; LogHelper.Info($"查询空筐筐缓存位 是否有空货位 库区编码={endarea}"); var endlocationlist = db.Queryable() .Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM == 0) .PartitionBy(a => a.N_ROW) .Take(1) .OrderBy(a => a.N_COL) .OrderBy(a => a.N_OROW) .ToList(); foreach (var item in endlocationlist) { var lockinfo = db.Queryable().Where(a => a.S_AREA_CODE == item.S_AREA_CODE && a.N_ROW == item.N_ROW && a.S_LOCK_STATE != "无").First(); if (lockinfo == null) { var endLayer = item.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, item.S_LOC_CODE, "翻斗机即产空筐下线(瓶坯)", trayCode, 1, endLayer, plc.deviceName, 1); break; } } //LogHelper.Info($"遍历查询缓存区的状态", "翻斗机"); //for (int i = 0; i < info.ProductArea.Count(); i++) //{ // string endarea = info.ProductArea[i]; // LogHelper.Info($"查询空筐筐缓存位 是否有空货位 库区编码={endarea}"); // var endLocation = db.Queryable().Where(a => a.S_AREA_CODE == endarea && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE.Trim() == "无").First(); // if (endlocation != null) // { // var endLayer = endLocation.N_CURRENT_NUM + 1; // result = DaMingShanCreateTransport(location, endLocation.S_LOC_CODE, "翻斗机即产空筐下线(瓶坯)", trayCode, 1, endLayer, plc.deviceName, 1); // break; // } //} } if (!result) { var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 4 && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (bitinfo != null) { var locinfo = db.Queryable().Where(q => q.S_AREA_CODE == bitinfo.location && q.N_CURRENT_NUM == 0 && q.S_LOCK_STATE.Trim() == "无").First(); if (locinfo != null) { var endLayer = locinfo.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, locinfo.S_LOC_CODE, "翻斗机即产空筐下线(瓶坯)", trayCode, 1, endLayer, plc.deviceName, 1); } } } if (result) { IntensiveArea.UnBindLocCntr(trayCode); } } } else { //非即产即用 直接入库缓存位 3+2 var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 4 && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (info != null && bitinfo != null) { string ItemName = info.ItemName; var locinfo = db.Queryable().Where(a => a.S_AREA_CODE == bitinfo.location && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE == "无").OrderBy(a => a.N_COL).First(); if (locinfo != null) { var endLayer = locinfo.N_CURRENT_NUM + 1; result = DaMingShanCreateTransport(location, locinfo.S_LOC_CODE, "翻斗机即产空筐下线(瓶坯)", trayCode, 1, endLayer, plc.deviceName, 1); } if (result) { IntensiveArea.UnBindLocCntr(trayCode); } } } return result; } /// /// 解绑物料信息 /// /// /// /// /// /// private static bool UnBindLocCntr(string trayCode) { bool result = true; List list = new List(trayCode.Split(',')); var db = new SqlHelper().GetInstance(); for (int i = 0; i < list.Count; i++) { if (db.Queryable().Count(a => a.S_CNTR_CODE.Trim() == list[i]) > 0) { db.Deleteable().Where(a => a.S_CNTR_CODE == list[i]).ExecuteCommand(); } } //1.0 查货位容器表 return result; } /// /// 创建搬运任务 /// /// /// /// /// /// /// /// /// /// public static bool DaMingShanCreateTransport(string start, string end, string taskType, string cntrs, int startLayer, int endLayer, string deviceName, int trayCarryCount = 1, int priority = 1, int itemLayer = 0, string workNo = "", string batch = "", string itemcode = "", string traytype = "") { var db = new SqlHelper().GetInstance(); var result = false; var taskNo = DateTime.Now.Ticks.ToString(); var res = TaskHelper.DaMingShanCreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, cntrs, deviceName, trayCarryCount, startLayer, endLayer, itemLayer, workNo, batch, itemcode, traytype); if (res) { result = true; //任务创建成功,起点货位出库锁定,终点货位入库锁定 LocationHelper.LockLoc(start, "出库锁"); LocationHelper.LockLoc(end, "入库锁"); if (taskType == "成品下线" && Settings.FULEenable == "1") { //IntensiveArea.SLlock(end); //成品下线任务生成成功,删除当前下线托盘中间表数据 List cntr = cntrs.Split(',').ToList(); db.Deleteable().Where(a => a.DeviceName.Trim() == deviceName).ExecuteCommand(); db.Deleteable().Where(it => cntr.Contains(it.trayCode)).ExecuteCommand();// && it.workNo == workNo.Trim() } } else { if (taskType == "成品下线" && Settings.FULEenable == "1") { db.Deleteable().Where(a => a.DeviceName.Trim() == deviceName).ExecuteCommand(); } } return result; } private static void SLlock(string end) { if (Settings.FULEenable == "1") { var db = new SqlHelper().GetInstance(); var info = db.Queryable().Where(a => a.S_LOC_CODE == end).First(); if (info != null) { TaskProcess.AreaRowLockState(info.N_ROW); } } } public static void ULlock(string end) { if (Settings.FULEenable == "1") { var db = new SqlHelper().GetInstance(); var info = db.Queryable().Where(a => a.S_LOC_CODE == end).First(); if (info != null) { TaskProcess.AreaRowLockState(info.N_ROW, false); } } } /// /// 缓存位入库 /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// public static Location DaMingShanGetCacheLocationIn(string area) { //库区货位约定:列号越小越靠里 Location result = null; try { //1.1 查到所有有容器的排 var db = new SqlHelper().GetInstance(); var list = db.Queryable().Where(a => a.S_AREA_CODE == area).ToList(); LogHelper.Info($"查询库区{area} 的货位数量为{list.Count()}"); if (list.Count > 0) { foreach (var a in list) { if (a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE.Trim() == "无") { result = a; break; } } } } catch (Exception ex) { //Console.WriteLine("GetLocationIn:" + ex.Message + ex.StackTrace); LogHelper.Error("GetLocationIn:" + ex.Message, ex); } return result; } /// /// 输送线叫空托 /// /// /// internal static Location GetEmptyOut(string areaCode, string traytype) { LogHelper.Info($"输送线:空托库区出库算法开始", "输送线"); Location result = null; var list = new SqlHelper().GetInstance().Queryable().Where(a => a.S_AREA_CODE == areaCode && a.N_CURRENT_NUM > 0).Includes(a => a.LocCntrRel).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); LogHelper.Info($"输送线:该库区可用库位数量为{list.Count}", "输送线"); for (int i = 0; i < list.Count; i++) { if (list[i].LocCntrRel != null) { LogHelper.Info($"判断货位{list[i].S_LOC_CODE} 板型{list[i].LocCntrRel.S_TRAY_TYPE} 与工单板型{traytype} 是否一致"); if (list[i].LocCntrRel.S_TRAY_TYPE == traytype) { LogHelper.Info($"输送线:库位{list[i].S_LOC_CODE} 判断是否有锁:{list[i].S_LOCK_STATE.Trim()}", "输送线"); if (list[i].S_LOCK_STATE.Trim() == "无") { result = list[i]; break; } } } } return result; } /// /// 缓存位出库 /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// public static Location DaMingShanGetCacheLocationOut(string area) { //库区货位约定:列号越小越靠里 Location result = null; try { //1.1 查到所有有容器的排 LogHelper.Info($"查询{area}库区所有的货位"); var db = new SqlHelper().GetInstance(); var trayList = new List(); var list = db.Queryable().Where(a => a.S_AREA_CODE.Trim() == area && a.N_CURRENT_NUM > 0 && a.S_LOCK_STATE.Trim() == "无").ToList(); LogHelper.Info($"货位数量为{list.Count()}"); if (list.Count > 0) { foreach (var a in list) { //if (a.N_CURRENT_NUM > 0 && a.S_LOCK_STATE.Trim() == "无") //{ //result = a; var trayNo = LocationHelper.GetLocCntrRel(a.S_LOC_CODE); if (trayNo != null) { foreach (var item in trayNo) { trayList.Add(item); } } //break; //} } if (trayList.Count > 0) { var cntr = trayList.OrderBy(a => a.T_CREATE).First(); result = db.Queryable().Where(a => a.S_LOC_CODE == cntr.S_LOC_CODE).Includes(a => a.LocCntrRel).First(); } } LogHelper.Info($"算法结束 结果{result != null}"); } catch (Exception ex) { //Console.WriteLine("GetLocationIn:" + ex.Message + ex.StackTrace); LogHelper.Error("GetLocationIn:" + ex.Message, ex); } return result; } /// /// 缓存位出库 /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// public static Location DaMingShanGetCacheLocationOut2(string area, string itemcode) { //库区货位约定:列号越小越靠里 Location result = null; try { //1.1 查到所有有容器的排 LogHelper.Info($"查询{area}库区所有的货位"); var db = new SqlHelper().GetInstance(); var list = db.Queryable().Where(a => a.S_AREA_CODE.Trim() == area).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList(); LogHelper.Info($"货位数量为{list.Count()}"); if (list.Count > 0) { foreach (var a in list) { if (a.N_CURRENT_NUM > 0 && a.S_LOCK_STATE.Trim() == "无" && a.LocCntrRel.CntrItemRel.S_ITEM_CODE == itemcode) { result = a; break; } } } LogHelper.Info($"算法结束 结果{result != null}"); } catch (Exception ex) { //Console.WriteLine("GetLocationIn:" + ex.Message + ex.StackTrace); LogHelper.Error("GetLocationIn:" + ex.Message, ex); } return result; } /// /// 注塑机出库、翻斗机出库 /// /// /// /// true:注塑机 false:翻斗机 /// internal static bool DaMingShanPLCOut(Settings.deviceInfo plc, string location, bool v, PGWorkOrder workOrder) { string startlocation = ""; var tasktype = ""; var db = new SqlHelper().GetInstance(); bool result = false; if (v) { //注塑机出库 var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == workOrder.S_LinkLineNo && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (info != null) { //瓶盖机即产即用 if (info != null) { string ItemName = info.ItemName; if (workOrder.S_UsingNow == "Y") { tasktype = "注塑即产空筐上线(瓶胚)"; } else { tasktype = "注塑库存空筐上线(瓶胚)"; } //查询对应终点的库位状态 if (info.ProductLocation.Count() > 0) { foreach (var a in info.ProductLocation) { var startlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a).First(); if (startlocationinfo != null) { if (startlocationinfo.N_CURRENT_NUM > 0 && startlocationinfo.S_LOCK_STATE.Trim() == "无") { startlocation = startlocationinfo.S_LOC_CODE.Trim(); result = DaMingShanCreateTransport(startlocation, location, tasktype, startlocationinfo.LocCntrRel.S_CNTR_CODE, 1, 1, plc.deviceName, 1); break; } } } } //对应终点找不到空闲货位 从对应库区寻找货位 if (!result) { if (info.IsDense == 0) { foreach (var item in info.ProductArea) { var startLocation = DaMingShanGetCacheLocationOut(item); if (startLocation != null) { var cntrList = LocationHelper.GetLocCntrRel(startLocation.S_LOC_CODE.Trim()); //淳安两个托盘为 一个 货位当前容量 var trayInfo = new LocCntrRel(); if (cntrList.Count >= 1) { //string cntrs = ""; trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(1).First();//单托出库 } result = DaMingShanCreateTransport(startLocation.S_LOC_CODE, location, tasktype, trayInfo.S_CNTR_CODE, 1, 1, plc.deviceName, 1); break; } } } else { for (int i = 0; i < info.ProductArea.Count(); i++) { string startarea = info.ProductArea[i]; var startbitlist = db.Queryable() .Where(a => a.S_AREA_CODE == startarea && a.N_CURRENT_NUM > 0 && a.S_LOCK_STATE == "无") .PartitionBy(a => a.N_OROW) .Take(1) .OrderByDescending(a => a.N_COL) .ToList(); foreach (var item in startbitlist) { var lockinfo = db.Queryable().Where(a => a.S_AREA_CODE == item.S_AREA_CODE && a.N_ROW == item.N_ROW && a.S_LOCK_STATE != "无").First(); if (lockinfo == null) { var cntrList = LocationHelper.GetLocCntrRel(item.S_LOC_CODE.Trim()); //淳安两个托盘为 一个 货位当前容量 var trayInfo = new LocCntrRel(); if (cntrList.Count >= 1) { //string cntrs = ""; trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(1).First();//单托出库 } result = DaMingShanCreateTransport(item.S_LOC_CODE, location, tasktype, trayInfo.S_CNTR_CODE, 1, 1, plc.deviceName, 1); break; } } if (result) break; } } } } } } //else //{ // //翻斗机入库 // LogHelper.Info($"翻斗机补满筐"); // var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == plc.deviceName && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); // if (info != null) // { // LogHelper.Info($"查询到满筐缓存区信息 location={JsonConvert.SerializeObject(info.ProductLocation)} area={JsonConvert.SerializeObject(info.ProductArea)}"); // string ItemName = info.ItemName; // //查询对应终点的库位状态 // if (info.ProductLocation.Count() > 0) // { // foreach (var a in info.ProductLocation) // { // var startlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a).First(); // if (startlocationinfo != null) // { // if (startlocationinfo.N_CURRENT_NUM > 0 && startlocationinfo.S_LOCK_STATE.Trim() == "无") // { // startlocation = startlocationinfo.S_LOC_CODE.Trim(); // result = DaMingShanCreateTransport(startlocation, location, "翻斗机补满筐", startlocationinfo.LocCntrRel.S_CNTR_CODE, 1, 1, plc.deviceName, 1, 1, 1); // break; // } // } // } // } // //对应终点找不到空闲货位 从对应库区寻找货位 // if (!result) // { // LogHelper.Info($"查询满筐缓存区"); // foreach (var item in info.ProductArea) // { // var startLocation = DaMingShanGetCacheLocationOut(item); // if (startLocation != null) // { // var startlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == startLocation.S_LOC_CODE).Includes(a => a.LocCntrRel, a => a.CntrItemRel).First(); // result = DaMingShanCreateTransport(startLocation.S_LOC_CODE, location, "翻斗机补满筐", startlocationinfo.LocCntrRel.S_CNTR_CODE, 1, 1, plc.deviceName, 1, 1, 1); // break; // } // } // } // } //} return result; } /// /// 瓶坯翻斗机 瓶盖翻斗机 /// /// /// /// true:注塑机 false:翻斗机 /// internal static bool DaMingShanPLCOut3(Settings.deviceInfo plc, string location, bool v, PGWorkOrder workorder) { string startlocation = ""; var tasktype = ""; var db = new SqlHelper().GetInstance(); bool result = false; if (v) { //注塑翻斗机叫料 var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == workorder.S_LinkLineNo && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); if (info != null) { LogHelper.Info($"查询到满筐缓存区信息 location={JsonConvert.SerializeObject(info.ProductLocation)} area={JsonConvert.SerializeObject(info.ProductArea)}"); string ItemName = info.ItemName; if (workorder.S_UsingNow == "Y") { tasktype = "翻斗机即产满筐上线(瓶胚)"; } else { tasktype = "翻斗机库存满筐上线(瓶胚)"; } //查询对应终点的库位状态 if (info.ProductLocation.Count() > 0) { foreach (var a in info.ProductLocation) { var startlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a).First(); if (startlocationinfo != null) { if (startlocationinfo.N_CURRENT_NUM > 0 && startlocationinfo.S_LOCK_STATE.Trim() == "无") { startlocation = startlocationinfo.S_LOC_CODE.Trim(); result = DaMingShanCreateTransport(startlocation, location, tasktype, startlocationinfo.LocCntrRel.S_CNTR_CODE, startlocationinfo.N_CURRENT_NUM, 1, plc.deviceName, 1, 1, 1); break; } } } } //对应终点找不到空闲货位 从对应库区寻找货位 if (!result) { LogHelper.Info($"查询满筐缓存区"); foreach (var item in info.ProductArea) { Location startLocation = null; if (plc.deviceName != "Y9坯" && plc.deviceName != "Y7盖") { startLocation = DaMingShanGetCacheLocationOut(item); } else { //起点密集型 startLocation = DaMingShanGetCacheLocationOut1(item); } if (startLocation != null) { var startlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == startLocation.S_LOC_CODE).Includes(a => a.LocCntrRel, a => a.CntrItemRel).First(); result = DaMingShanCreateTransport(startLocation.S_LOC_CODE, location, tasktype, startlocationinfo.LocCntrRel.S_CNTR_CODE, startlocationinfo.N_CURRENT_NUM, 1, plc.deviceName, 1, 1, 1); break; } } } } } else { //瓶盖翻斗机叫料 LogHelper.Info($"翻斗机补满筐"); var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == plc.deviceName && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); if (info != null) { LogHelper.Info($"查询到满筐缓存区信息 location={JsonConvert.SerializeObject(info.ProductLocation)} area={JsonConvert.SerializeObject(info.ProductArea)}"); string ItemName = info.ItemName; if (workorder.S_UsingNow == "Y") { tasktype = "翻斗机即产满筐上线(瓶盖)"; } else { tasktype = "翻斗机库存满筐上线(瓶盖)"; } //查询对应终点的库位状态 if (info.ProductLocation.Count() > 0) { foreach (var a in info.ProductLocation) { var startlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a).First(); if (startlocationinfo != null) { if (startlocationinfo.N_CURRENT_NUM > 0 && startlocationinfo.S_LOCK_STATE.Trim() == "无") { startlocation = startlocationinfo.S_LOC_CODE.Trim(); result = DaMingShanCreateTransport(startlocation, location, tasktype, startlocationinfo.LocCntrRel.S_CNTR_CODE, startlocationinfo.N_CURRENT_NUM, 1, plc.deviceName, 1, 1, 1); break; } } } } //对应终点找不到空闲货位 从对应库区寻找货位 if (!result) { LogHelper.Info($"查询满筐缓存区"); foreach (var item in info.ProductArea) { Location startLocation = null; if (plc.deviceName != "Y9坯" && plc.deviceName != "Y7盖") { startLocation = DaMingShanGetCacheLocationOut(item); } else { //起点密集型 startLocation = DaMingShanGetCacheLocationOut1(item); } if (startLocation != null) { var startlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == startLocation.S_LOC_CODE).Includes(a => a.LocCntrRel, a => a.CntrItemRel).First(); result = DaMingShanCreateTransport(startLocation.S_LOC_CODE, location, tasktype, startlocationinfo.LocCntrRel.S_CNTR_CODE, startLocation.N_CURRENT_NUM, 1, plc.deviceName, 1, 1, 1); break; } } } } } return result; } private static Location DaMingShanGetCacheLocationOut1(string areaNo) { Location result = null; var db = new SqlHelper().GetInstance(); var startbitlist = db.Queryable() .Where(a => a.S_AREA_CODE == areaNo && a.N_CURRENT_NUM > 0) .Select(it => new { sum = SqlFunc.AggregateSum(it.N_CURRENT_NUM), it.N_ROW }) .GroupBy(it => it.N_ROW) .MergeTable() .OrderByDescending(it => it.sum) .ToList(); foreach (var item in startbitlist) { var lockinfo = db.Queryable().Where(a => a.S_AREA_CODE == areaNo && a.N_ROW == item.N_ROW && a.S_LOCK_STATE != "无").First(); if (lockinfo == null) { result = db.Queryable().Where(a => a.S_AREA_CODE == areaNo && a.N_ROW == item.N_ROW && a.N_CURRENT_NUM > 0) .OrderByDescending(a => a.N_COL) .Includes(a => a.LocCntrRel) .First(); break; } } return result; } /// /// 瓶盖机补空筐 /// /// /// /// true:即产即用 false:非即产即用 /// internal static bool DaMingShanPLCOut2(Settings.deviceInfo plc, string location, bool v, PGWorkOrder workOrder) { string startlocation = ""; var tasktype = ""; var db = new SqlHelper().GetInstance(); bool result = false; var info = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == plc.deviceName && a.Enable == "1" && a.ItemTrayType == "空").FirstOrDefault(); if (v) { //瓶盖机即产即用 if (info != null) { string ItemName = info.ItemName; if (workOrder.S_UsingNow == "Y") { tasktype = "注塑即产空筐上线(瓶盖)"; } else { tasktype = "注塑库存空筐上线(瓶盖)"; } //查询对应终点的库位状态 if (info.ProductLocation.Count() > 0) { foreach (var a in info.ProductLocation) { var startlocationinfo = db.Queryable().Where(b => b.S_LOC_CODE == a).First(); if (startlocationinfo != null) { if (startlocationinfo.N_CURRENT_NUM > 0 && startlocationinfo.S_LOCK_STATE.Trim() == "无") { startlocation = startlocationinfo.S_LOC_CODE.Trim(); result = DaMingShanCreateTransport(startlocation, location, tasktype, startlocationinfo.LocCntrRel.S_CNTR_CODE, 1, 1, plc.deviceName, 1); break; } } } } //对应终点找不到空闲货位 从对应库区寻找货位 if (!result) { foreach (var item in info.ProductArea) { var startLocation = DaMingShanGetCacheLocationOut(item); if (startLocation != null) { var cntrList = LocationHelper.GetLocCntrRel(startLocation.S_LOC_CODE.Trim()); //淳安两个托盘为 一个 货位当前容量 var trayInfo = new LocCntrRel(); if (cntrList.Count >= 1) { //string cntrs = ""; trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(1).First();//单托出库 } result = DaMingShanCreateTransport(startLocation.S_LOC_CODE, location, tasktype, trayInfo.S_CNTR_CODE, 1, 1, plc.deviceName, 1); break; } } } } } //else //{ // //瓶盖机非即产即用 // // //非即产即用 直接入库缓存位 3+2 // var bitinfo = Settings.GetinStockCacheBitList().Where(a => a.deviceType == 1 && a.Enable == "1" && a.ItemTrayType == "满").FirstOrDefault(); // if (info != null && bitinfo != null) // { // string ItemName = info.ItemName; // var locinfo = db.Queryable().Where(q => q.S_LOC_CODE == bitinfo.location).First(); // if (locinfo != null) // { // if (locinfo.S_LOCK_STATE == "无") // { // var cntrList = LocationHelper.GetLocCntrRel(locinfo.S_LOC_CODE.Trim()); // //淳安两个托盘为 一个 货位当前容量 // var trayInfo = new LocCntrRel(); // if (cntrList.Count >= 1) // { // string cntrs = ""; // trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Take(1).First();//单托出库 // } // var startley = cntrList.Count(); // result = DaMingShanCreateTransport(location, locinfo.S_LOC_CODE, "注塑即产满筐下线(瓶坯)", trayInfo.S_CNTR_CODE, startley, 1, plc.deviceName, 1); // } // } // } //} return result; } /// /// 标准出入库处理 /// /// 起点点位 或 终点点位 /// 任务类型 /// 托盘编码 /// 库区编码 /// 物料编码 /// 批次号 /// 物料层数 /// 物料托盘类型 /// 动作类型 True-入库 False-出库 /// internal static bool DaMingShanPlcTask(string bit, string taskType, string trayCode, string areaCode, string itemCode, string batchNo, string itemLayer, string itemTrayType, string deviceName, bool actionType, string workNo = "") { var result = false; LogHelper.Info($"成品入库算法匹配终点,产线号={deviceName},库区={areaCode},物料编码={itemCode},批次号={batchNo}", "输送线"); //1.任务创建:锁定起点,终点,终点排号-排锁定表(任务完成解锁), // 任务数据携带-托盘码(便于回报)--两个托盘码存入任务表 WMSTask 的 托盘字段 S_CNTRS // 物料层数(NDC下发必要参数) --起点层数 N_START_LAYER :默认为1 // --终点层数 N_END_LAYER :获取 货位表-终点货位信息 N_CAPACITY + 1 //2.插入 当前排号、产线号 至 自动移库中间表,等待工单完成即进行 自动移库 var db = new SqlHelper().GetInstance(); var info = db.Queryable().Where(a => a.S_ITEM_CODE == itemCode && a.S_ITEM_MODEL == itemLayer).First(); if (info != null) { if (actionType) { var endLocation = GetLocationIn(areaCode, itemCode, batchNo, deviceName, itemLayer); if (endLocation != null) { var endLayer = endLocation.N_CURRENT_NUM + 1; //DaMingShanAnalysisMoveLib model = new DaMingShanAnalysisMoveLib { RowNo = endLocation.N_ROW, Batch = batchNo, DeviceName = deviceName }; //WCSHelper.DaMingShanInsertAnalysisMoveLib(model); result = DaMingShanCreateTransport(bit, endLocation.S_LOC_CODE, taskType, trayCode, 1, endLayer, deviceName, 1, 1, int.Parse(info.S_ITEM_LAYER), workNo, batchNo, itemCode, itemTrayType); } //else //Console.WriteLine($"MoboxHelperCreateTask: 未找到终点货位"); } else { var startLocation = GetLocationOut(areaCode, itemCode, batchNo, itemLayer); if (startLocation != null) { var startLayer = startLocation.N_CURRENT_NUM; var taskNo = DateTime.Now.Ticks.ToString(); //淳安只需要一个一拿 //var carryCount = startLocation.N_CURRENT_NUM > 3 ? startLocation.N_CURRENT_NUM - 3 : startLocation.N_CURRENT_NUM; //出库要从起点获取托盘 var cntrList = LocationHelper.GetLocCntr(startLocation.S_LOC_CODE); //淳安两个托盘为 一个 货位当前容量 if (cntrList.Count == startLocation.N_CURRENT_NUM * 2) { string cntrs = ""; var trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Skip(2).ToList(); trayInfo.ForEach(a => { cntrs = cntrs + "," + a.S_CNTR_CODE.Trim(); }); result = DaMingShanCreateTransport(startLocation.S_LOC_CODE, bit, taskType, cntrs, startLayer, 1, deviceName, 1, 1); } else { //Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】"); } } } } LogHelper.Info($"创建任务是否成功 {result}"); return result; } #endregion } }