using HH.WCS.Hexafluo.util;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
|
namespace HH.WCS.Hexafluo.wms
|
{
|
/// <summary>
|
/// 密集型库区
|
/// </summary>
|
internal class IntensiveArea
|
{
|
static IntensiveArea()
|
{
|
//InitRowLockTable(new List<string> { "PGKQ", "PGKTK" });
|
}
|
|
/// <summary>
|
/// 根据库区和物料获取入库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在)
|
/// </summary>
|
/// <param name="area"></param>
|
/// <param name="itemCode">如果itemCode是空表示空容器</param>
|
/// <param name="standardCarryQty">标准搬运数量</param>
|
/// <returns></returns>
|
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<Location>().GetInstance().Queryable<Location>().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<object>().GetInstance();
|
var list = db.Queryable<Location>().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)
|
{
|
list = list.OrderBy(e => e.N_ROW).ThenBy(e => e.N_COL).ToList();
|
//1.21 加载货位的容器信息 (mapper之前只能是查询原始数据,如果有其他查询 mapper失效)
|
#region MyRegion
|
/*
|
Console.WriteLine("加载货位的容器信息");
|
db.ThenMapper(list, loc => {
|
loc.LocCntrRel = db.Queryable<LocCntrRel>().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<CntrItemRel>().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<Location>().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<Location>().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<Location>().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<Location>().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;
|
}
|
|
|
public static Location GetLocation5In(string area, string S_SPEC, string itemBatch, int standardCarryQty = 1)
|
{
|
Location result = null;
|
|
try
|
{
|
//1.0 获取每一排最大的列
|
//1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除
|
var listMaxCol = new SqlHelper<Location>().GetInstance().Queryable<Location>().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<object>().GetInstance();
|
var list = db.Queryable<Location>().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)
|
{
|
list = list.OrderBy(e => e.N_ROW).ThenBy(e => e.N_COL).ToList();
|
//1.21 加载货位的容器信息 (mapper之前只能是查询原始数据,如果有其他查询 mapper失效)
|
#region MyRegion
|
/*
|
Console.WriteLine("加载货位的容器信息");
|
db.ThenMapper(list, loc => {
|
loc.LocCntrRel = db.Queryable<LocCntrRel>().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<CntrItemRel>().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 ((S_SPEC != null && list[i].LocCntrRel.CntrItemRel != null && list[i].LocCntrRel.CntrItemRel.S_ITEM_SPEC.Trim() == S_SPEC && list[i].LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == itemBatch.Trim()) || (S_SPEC == 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<Location>().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<Location>().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<Location>().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<Location>().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;
|
}
|
|
/// <summary>
|
/// 根据库区和物料获取出库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在)
|
/// </summary>
|
/// <param name="area"></param>
|
/// <param name="itemCode">如果itemCode是空表示空容器</param>
|
/// <param name="standardCarryQty">标准搬运数量</param>
|
/// <returns></returns>
|
/// <returns></returns>
|
public static Location GetLocation4Out(string area, string itemCode, string itemBatch, int standardCarryQty = 1)
|
{
|
Console.WriteLine($"area={area}");
|
Location result = null;
|
var db = new SqlHelper<Location>().GetInstance();
|
|
//1.0 查到所有有容器的排 var list = db.Queryable<Location>().Where(a => a.N_CURRENT_NUM>0).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList();
|
var list = db.Queryable<Location>().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<LocCntrRel>().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<CntrItemRel>().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<Location>().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;
|
}
|
|
/// <summary>
|
/// 初始化密集排锁表格
|
/// </summary>
|
private static void InitRowLockTable(List<string> areas)
|
{
|
var db = new SqlHelper<object>().GetInstance();
|
var listRowLocks = db.Queryable<RowLock>().ToList();
|
areas.ForEach(a =>
|
{
|
var list = db.Queryable<Location>().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<RowLock>(new RowLock { N_ROW = r, S_AREA_CODE = a, S_LOCK_STATE = "无", S_LOCK_SRC = "", S_WORK_MODE = "正常" }).ExecuteCommand();
|
}
|
});
|
|
});
|
}
|
|
private static List<int> GetRowsByArea(string area)
|
{
|
var list = new SqlHelper<Location>().GetInstance().Queryable<Location>().Where(a => a.S_AREA_CODE == area).Distinct().Select(a => a.N_ROW).ToList();
|
return list;
|
}
|
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<Location>().GetList();
|
//var LocCntrRels = new SqlHelper<LocCntrRel>().GetList();
|
//var CntrItemRels = new SqlHelper<CntrItemRel>().GetList();
|
|
//var list = new SqlHelper<Location>().GetInstance().Queryable<Location>().LeftJoin<LocCntrRel>((l, lc) => l.S_LOC_CODE == lc.S_LOC_CODE).ToList();
|
//var results = context.Client.Queryable<Employee>().Mapper(t=>t.Person, p=>p.PersonId).ToList();
|
var db = new SqlHelper<object>().GetInstance();
|
|
//var list = db.Queryable<Location>().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<Location>().Where(a => a.N_CURRENT_NUM > 0).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList();
|
|
|
|
#region MyRegion
|
/*
|
// SetContext不会生成循环操作,高性能 和直接Where性能是不一样的
|
var list = db.Queryable<Location>().Where(a => a.N_CURRENT_NUM > 0).ToList();
|
//第一层
|
db.ThenMapper(list, loc => {
|
loc.LocCntrRel = db.Queryable<LocCntrRel>().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault();
|
});
|
//第二层
|
db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => {
|
lcr.CntrItemRel = db.Queryable<CntrItemRel>().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault();
|
});
|
*/
|
#endregion
|
}
|
|
}
|
}
|