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
}
}