using HH.WMS.BLL.Common; using HH.WMS.Common; using HH.WMS.Common.Algorithm; using HH.WMS.DAL.Algorithm; using HH.WMS.DAL.Basic; using HH.WMS.Entitys.Algorithm; using HH.WMS.Entitys.Basic; using HH.WMS.Entitys.Common; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using HH.WMS.DAL.InStock; using Newtonsoft.Json; using HH.WMS.Entitys.Autobom; using HH.WMS.Entitys; using HH.WMS.Entitys.Sys; namespace HH.WMS.BLL.Algorithm { /// /// 入库算法业务层 /// public class In_AlgorBLL : BaseBLL { /**************非作业区入库算法(平库、立库) 开始/**************/ #region 非作业区 入库算法 /// /// 入库算法 /// /// public InResultEntity In(InAlgorEnitty model) { Log.AlgorInfo("In", "入库算法参数:" + JsonConvert.SerializeObject(model)); //定义返回实体 InResultEntity resultEntity = new InResultEntity(); resultEntity.Success = false; resultEntity.Msg = "库区货位不足"; #region 传入参数判断 //判断参数实体 if (model == null) { resultEntity.Success = false; resultEntity.Msg = "参数实体不能为 null !"; return resultEntity; } //判断库区不能为空 if (string.IsNullOrEmpty(model.stockAreaCode)) { resultEntity.Success = false; resultEntity.Msg = "库区编码不能为空!"; return resultEntity; } //判断托盘码不能为空 //if (string.IsNullOrEmpty(model.trayCode)) //{ // resultEntity.Success = false; // resultEntity.Msg = "托盘码不能为空!"; // return resultEntity; //} //必须指定获取的货位数量 if (model.locationQty == 0) { resultEntity.Success = false; resultEntity.Msg = "请指定获取货位的数量!"; return resultEntity; } #endregion //获取该库区结构类型(流离式、平库、立库) string areaType = CreateDAL().GetAreaTypeByCode(model.stockAreaCode); List lstDevice = model.lstDevice; if (areaType == "平库" || areaType == "立库") { if (!string.IsNullOrEmpty(model.itemCode)) { //指定物料 resultEntity = In_ItemCode(model.itemCode, model.logicCode, model.stockAreaCode, model.locationQty, model.lstDevice, model.lockLocation); } else { //不指定物料,空托盘入库 resultEntity = In_TrayCode(model.stockAreaCode, model.logicCode, model.locationQty, model.lstDevice, model.lockLocation); } } Log.AlgorInfo("In—算法结束", "计算结果:" + JsonConvert.SerializeObject(resultEntity)); return resultEntity; } #endregion #region 非作业区 平库立库入库算法 #region 非作业区立库入库算法 指定物料(通过库区关联逻辑分区,物料关联逻辑分区) /// /// 入库 指定物料(通过库区关联逻辑分区,物料关联逻辑分区) /// /// 物料编码 /// 逻辑分区编码 /// 库区编码 /// 需要货位的数量 /// 设备信息 AMS给出 /// private InResultEntity In_ItemCode(string itemCode, string logicCode, string stockAreaCode, int locationQty, List lstDevice, bool lockLocation) { InResultEntity resultEntity = new InResultEntity(); //需要纳入计算的逻辑分区集合 List lstLogic = new List(); string logicCheckMsg = string.Empty; //如果逻辑分区为空 if (string.IsNullOrEmpty(logicCode)) { lstLogic = GetLogicList(itemCode, stockAreaCode, out logicCheckMsg); if (!string.IsNullOrEmpty(logicCheckMsg)) { resultEntity.Success = false; resultEntity.Msg = logicCheckMsg; return resultEntity; } } else//逻辑分区不为空 { #region 固定逻辑分区和库区 //将逻辑分区编码转换成List List lstLogics = new List(logicCode.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries)); //通过逻辑分区编码集合以及库区编码获得逻辑分区仓库/库区/货位关联 List lstLogicEntityByArea = CreateDAL().GetLogicListByLogicAndArea(lstLogics, stockAreaCode); lstLogic = lstLogicEntityByArea.Select(o => new LogicTrue { stockCode = o.CN_S_STOCK_CODE, areaCode = o.CN_S_STOCK_AREA, locationCode = o.CN_S_LOCATION_CODE, stockarea_position = o.CN_S_PRIORITY, type = o.CN_N_TYPE }).OrderBy(o => o.stockarea_position).ToList(); if (lstLogic == null || lstLogic.Count == 0) { resultEntity.Success = false; resultEntity.Msg = "根据逻辑分区编码集合以及库区编码未获得对应的逻辑分区!"; return resultEntity; } #endregion } //调用通过逻辑分区取货位的算法 List lstLocations = AlgorIn(stockAreaCode, locationQty, lstDevice, lstLogic, lockLocation); if (lstLocations != null && lstLocations.Count > 0) { resultEntity.Success = true; resultEntity.lstLocation = lstLocations; } else { resultEntity.Success = false; resultEntity.Msg = "计算未得到货位!"; } return resultEntity; } #endregion #region 非作业区立库入库算法 不指定物料(直接通过库区计算货位) /// /// 入库 不指定物料(直接通过库区对应逻辑分区计算货位) /// /// /// /// /// /// private InResultEntity In_TrayCode(string stockAreaCode, string logicCode, int locationQty, List lstDevice, bool lockLocation) { //返回类型 InResultEntity resultEntity = new InResultEntity(); //需要纳入计算的逻辑分区集合 List lstLogic = new List(); //如果逻辑分区不为空 if (!string.IsNullOrEmpty(logicCode)) { List lstLogics = new List(logicCode.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries)); //通过逻辑分区编码集合以及库区编码获得逻辑分区仓库/库区/货位关联 List lstLogicEntityByArea = CreateDAL().GetLogicListByLogicAndArea(lstLogics, stockAreaCode); lstLogic = lstLogicEntityByArea.Select(o => new LogicTrue { stockCode = o.CN_S_STOCK_CODE, areaCode = o.CN_S_STOCK_AREA, locationCode = o.CN_S_LOCATION_CODE, stockarea_position = o.CN_S_PRIORITY, type = o.CN_N_TYPE }).OrderBy(o => o.stockarea_position).ToList(); if (lstLogic == null || lstLogic.Count == 0) { resultEntity.Success = false; resultEntity.Msg = "根据逻辑分区编码集合以及库区编码未获得对应的逻辑货位!"; return resultEntity; } } else { LogicTrue logicModel = new LogicTrue(); logicModel.areaCode = stockAreaCode; logicModel.item_position = "1"; logicModel.locationCode = ""; logicModel.stockarea_position = "1"; logicModel.stockCode = ""; logicModel.type = 2; lstLogic.Add(logicModel); } List lstLocations = AlgorIn(stockAreaCode, locationQty, lstDevice, lstLogic, lockLocation); if (lstLocations != null && lstLocations.Count > 0) { resultEntity.Success = true; resultEntity.lstLocation = lstLocations; } else { resultEntity.Success = false; resultEntity.Msg = "计算未得到货位!"; } return resultEntity; } #endregion #region 非作业区立库入库算法 通过逻辑分区计算符合条件的货位信息(指定物料专用) /// /// 计算 通过逻辑分区计算符合条件的货位信息(指定物料专用) /// /// 获得空位的数量 /// 设备信息 /// 逻辑分区详细 /// private List AlgorIn(string areaCode, int locationQty, List lstDevice, List lstLogic, bool lockLocation) { //货位列表 List lstLocations = new List(); //循环逻辑分区关联的仓库/库区/货位 foreach (LogicTrue logicEntity in lstLogic) { //获得真实可用的货位数据 Log.AlgorInfo("In_AlgorBLL-AlgorIn", "logicEntity实体数据" + JsonConvert.SerializeObject(logicEntity)); List lstTrueLocation = GetLocationByArea_R(logicEntity); Log.AlgorInfo("In_AlgorBLL-AlgorIn", "获得真实可用的货位数据结束" + lstTrueLocation.Count); if (lstTrueLocation == null || lstTrueLocation.Count == 0) { continue; } //需要货位的数量 = 前台传递需要的数量-已获得数量 int GetQty = locationQty - lstLocations.Count; //添加货位 lstLocations.AddRange(GetLocationsByStrategyAlgor(areaCode, GetQty, ref lstDevice, ref lstTrueLocation, lockLocation)); //如果货位数量足够 则结束循环 if (lstLocations.Count >= locationQty) { break; } } return lstLocations; } #endregion #region 非作业区立库入库算法 利用入库策略计算得到货位列表(公用) /// /// 利用入库策略计算得到货位列表(公用) /// /// /// /// /// public List GetLocationsByStrategyAlgor(string areaCode, int locationQty, ref List lstDevice, ref List lstTrueLocation, bool lockLocation) { #region 查询该库区配置的入库策略及优先级 List lstStrategy = new List(); lstStrategy = CreateDAL().GetStrateListByAreaOrStock("", areaCode, "入库"); List lstStrate = lstStrategy.OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList(); #endregion //策略实体 AlgorTacticsCommon Trctics = new AlgorTacticsCommon(); List lstTmp_Location = new List(); //返回货位实体列表 List lstLocations = new List(); for (int i = 0; i < locationQty; i++) { locationEntity l_Entity = new locationEntity(); string deviceCode = string.Empty; lstTmp_Location = CalculateLocByStegy(ref lstDevice, lstTrueLocation, lstStrate, out deviceCode); //如果没有可计算的货位 则直接结束循环 if (lstTmp_Location == null || lstTmp_Location.Count == 0) { break; } string location_true = lstTmp_Location[0].CN_S_LOCATION_CODE;//货位编码 int agv_location_true = lstTmp_Location[0].CN_N_AGV_LOCATION;//对应AGV编号 //更新货位状态 if (lockLocation) { SqlExecuteResult result = CreateDAL().UpdateLocationState(location_true, Constants.Location_State_InLock, "入库", null); Log.AlgorInfo("更新货位状态-UpdateLocationState", "货位" + location_true + "更改为预入库锁定,执行结果为:" + result.Success.ToString() + result.Row.ToString()); if (result.Success && result.Row > 0) { l_Entity.locationCode = location_true;//货位编码 l_Entity.avcLocationCode = agv_location_true;//对应AGV编号 //新增计算得到的货位 lstLocations.Add(l_Entity); if (!string.IsNullOrEmpty(deviceCode)) { //增加设备任务数 lstDevice = lstDevice.Select(o => { o.taskNum = o.deviceCode == deviceCode ? o.taskNum + 1 : o.taskNum; return o; }).ToList(); } } } else { l_Entity.locationCode = location_true;//货位编码 l_Entity.avcLocationCode = agv_location_true;//对应AGV编号 //新增计算得到的货位 lstLocations.Add(l_Entity); } //删除已经添加的货位 lstTrueLocation.RemoveAll(o => o.CN_S_LOCATION_CODE == location_true); } //如果未获得足够的货位并且可用货位还存在 if (lstLocations.Count < locationQty && lstTrueLocation.Count > 0) { //重新定义数量=前台传递过来的货位数-已获得的货位数量 int qty = locationQty - lstLocations.Count; lstLocations.AddRange(GetLocationsByStrategyAlgor(areaCode, qty, ref lstDevice, ref lstTrueLocation, lockLocation)); } return lstLocations; } #endregion #region 根据策略及优先级计算货位 public List CalculateLocByStegy(ref List lstDevice, List lstLocation, List lstStrate, out string deviceCode) { List lstFilterLoc = lstLocation; deviceCode = string.Empty; //策略实体 AlgorTacticsCommon Trctics = new AlgorTacticsCommon(); foreach (string stegy in lstStrate) { //逐个策略进行计算 switch (stegy) { case "EquipmentBalance": //设备均衡 lstFilterLoc = Trctics.EquipmentBalance(lstDevice, lstFilterLoc, out deviceCode); break; case "RoadWayBalance": //巷道均衡 lstFilterLoc = Trctics.RoadWayBalance(lstFilterLoc); ; break; case "NearbyBalance": //就近原则 lstFilterLoc = Trctics.NearbyBalance(lstFilterLoc); ; break; } } return lstFilterLoc; } #endregion #endregion /**************非作业区入库算法(可处理流离式、平库、立库)结束/**************/ #region 公用方法 根据物料、库区与逻辑分区的对应关系求交集 public List GetLogicList(string itemCode, string stockAreaCode, out string errMsg) { errMsg = ""; #region 通过物料取逻辑分区 逻辑分区关联物料 //需要纳入计算的逻辑分区集合 List lstLogic = new List(); //逻辑分区集合 List lstLogicEntityByItem = CreateDAL().GetPartitionItem(itemCode, 2); if (lstLogicEntityByItem == null || lstLogicEntityByItem.Count == 0) { //根据物料编码获得物料信息 AutoBomItemEntity itemEntity = CreateDAL().GetItemEntity(itemCode); if (itemEntity != null && !string.IsNullOrEmpty(itemEntity.CN_S_STORE_TYPE)) { //获得物料类型 string itemType = itemEntity.CN_S_STORE_TYPE; lstLogicEntityByItem = CreateDAL().GetPartitionItem(itemType, 1); } } #endregion //如果物料未分配逻辑分区则根据库区编码计算货位 if (lstLogicEntityByItem == null || lstLogicEntityByItem.Count == 0) { //errMsg = "根据物料编码未获得对应的逻辑分区!"; LogicTrue logicModel = new LogicTrue(); logicModel.areaCode = stockAreaCode; logicModel.item_position = "1"; logicModel.locationCode = ""; logicModel.stockarea_position = "1"; logicModel.stockCode = ""; logicModel.type = 2; lstLogic.Add(logicModel); } else { #region 通过库区取逻辑分区 逻辑分区关联仓库/库区/货位 List lstLogicEntityByArea = CreateDAL().GetLogicListByAreaCode(stockAreaCode); //如果物料未分配逻辑分区则返回空货位 if (lstLogicEntityByArea == null || lstLogicEntityByArea.Count == 0) { errMsg = "库区" + stockAreaCode + "或库区中货位未关联逻辑分区!"; } #endregion #region 取交集 //取交集 lstLogic = lstLogicEntityByItem.Join(lstLogicEntityByArea, u => u.CN_S_AREA_CODE, d => d.CN_S_AREA_CODE, (u, d) => new { u, d }) .Select(o => new LogicTrue { stockCode = o.d.CN_S_STOCK_CODE, areaCode = o.d.CN_S_STOCK_AREA, locationCode = o.d.CN_S_LOCATION_CODE, item_position = o.u.CN_S_PRIORITY, stockarea_position = o.d.CN_S_PRIORITY, type = o.d.CN_N_TYPE }).ToList(); if (lstLogic == null || lstLogic.Count == 0) { errMsg = "物料关联的逻辑货位与库区关联的货位不存在交集!"; } //排序 先根据物料优先级 再根据仓库/库区/货位优先级 lstLogic = lstLogic.OrderBy(o => o.item_position).OrderBy(o => o.stockarea_position).ToList(); #endregion } return lstLogic; } #endregion #region 公用方法 获得真实可用的货位数据(公用) /// /// 获得真实可用的货位数据 指已在关系型数据库中验证货位状态后的货位集合数据 /// /// 取交集后的逻辑分区列表 /// public List GetLocationByArea_R(LogicTrue model) { //用于存储真实可用的数据 注:此列表已在关系型数据库中验证了货位扩展表的状态 //可以用于入库策略计算与生成 List lstTrueLocation = new List(); //根据逻辑分区查询出来可用的货位列表 注:此列表暂未在关系型数据库中货位扩展验证状态 List locationCodes = new List(); List lstLocation = new List(); switch (model.type) { case 1://返回仓库对应的货位列表 lstLocation = CreateDAL().GetLocationByStockCode(model.stockCode); break; case 2://返回库区对应的货位列表 lstLocation = CreateDAL().GetLocationByAreaCode(model.areaCode); break; case 3://直接返回货位编号 locationCodes = new List(model.locationCode.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));// new List() { model.locationCode }; lstLocation = CreateDAL().GetLocationByLocationCode(locationCodes); break; case 4://返回库区对应的货位列表 lstLocation = CreateDAL().GetLocationByAreaCode(model.areaCode); break; case 5://返回库区对应的货位列表 locationCodes = new List() { model.locationCode }; lstLocation = CreateDAL().GetLocationByLocationCode(locationCodes); break; case 6://返回库区对应的货位列表 lstLocation = CreateDAL().GetLocationByAreaCode(model.areaCode); break; default: break; } if (lstLocation.Count > 0) { // Log.AlgorInfo("GetLocationByArea_R", "monogo中(lstLocation)中可用货位数据" + string.Join(",", lstLocation.Select(o => o.CN_S_LOCATION_CODE).ToList())); } else { Log.AlgorInfo("GetLocationByArea_R", "monogo中(lstLocation)没有数据" + lstLocation.Count); } //if (lstLocation.Count == 0) //{ // Log.Debug("Inasign", "TN_AB_STOCK_LOCATION中没有数据"); //} //else //{ // List locationLog = lstLocation.Select(o => o.CN_S_LOCATION_CODE).ToList(); // Log.Debug("Inasign", "TN_AB_STOCK_LOCATION中货位数据" + string.Join(",", locationLog)); //} //货位扩展表中可用的货位 //List locationTrueCodes = GetTrueLocationCodes(model.stockCode, locationCodes, model.type); List locationTrueCodes = GetTrueLocationCodes(model.stockCode.Trim(), model.areaCode, locationCodes, model.type); if (locationTrueCodes.Count == 0) { Log.AlgorInfo("GetLocationByArea_R", "货位扩展表中没有数据"); } //else //{ // List locationLog = locationTrueCodes.Select(o => o.CN_S_LOCATION_CODE).ToList(); // Log.AlgorInfo("GetLocationByArea_R", "tn_wm_b_location_ext中货位数据" + string.Join(",", locationLog)); //} if (locationTrueCodes != null && locationTrueCodes.Count != 0) { lstTrueLocation = lstLocation.Join(locationTrueCodes, u => u.CN_S_LOCATION_CODE, d => d.CN_S_LOCATION_CODE, (u, d) => new { u, d }) .Select(o => o.u).ToList(); } if (lstTrueLocation.Count == 0) { Log.AlgorInfo("GetLocationByArea_R", "lstTrueLocation中没有数据"); } else { List locationLog = lstTrueLocation.Select(o => o.CN_S_LOCATION_CODE).ToList(); Log.AlgorInfo("GetLocationByArea_R", "lstTrueLocation中货位数据" + string.Join(",", locationLog)); } return lstTrueLocation; } public List GetLocationByArea_R(LogicTrue model, string locationType) { //用于存储真实可用的数据 注:此列表已在关系型数据库中验证了货位扩展表的状态 //可以用于入库策略计算与生成 List lstTrueLocation = new List(); //根据逻辑分区查询出来可用的货位列表 注:此列表暂未在关系型数据库中货位扩展验证状态 List locationCodes = new List(); List lstLocation = new List(); switch (model.type) { case 1://返回仓库对应的货位列表 lstLocation = CreateDAL().GetLocationByStockCode(model.stockCode); break; case 2://返回库区对应的货位列表 lstLocation = CreateDAL().GetLocationByAreaCode(model.areaCode, locationType); break; case 3://直接返回货位编号 locationCodes = new List(model.locationCode.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));// new List() { model.locationCode }; lstLocation = CreateDAL().GetLocationByLocationCode(locationCodes, locationType); break; case 4://返回库区对应的货位列表 lstLocation = CreateDAL().GetLocationByAreaCode(model.areaCode); break; case 5://返回库区对应的货位列表 locationCodes = new List() { model.locationCode }; lstLocation = CreateDAL().GetLocationByLocationCode(locationCodes); break; case 6://返回库区对应的货位列表 lstLocation = CreateDAL().GetLocationByAreaCode(model.areaCode); break; default: break; } if (lstLocation.Count > 0) { // Log.AlgorInfo("GetLocationByArea_R", "monogo中(lstLocation)中可用货位数据" + string.Join(",", lstLocation.Select(o => o.CN_S_LOCATION_CODE).ToList())); } else { Log.AlgorInfo("GetLocationByArea_R", "monogo中(lstLocation)没有数据" + lstLocation.Count); } //if (lstLocation.Count == 0) //{ // Log.Debug("Inasign", "TN_AB_STOCK_LOCATION中没有数据"); //} //else //{ // List locationLog = lstLocation.Select(o => o.CN_S_LOCATION_CODE).ToList(); // Log.Debug("Inasign", "TN_AB_STOCK_LOCATION中货位数据" + string.Join(",", locationLog)); //} //货位扩展表中可用的货位 //List locationTrueCodes = GetTrueLocationCodes(model.stockCode, locationCodes, model.type); List locationTrueCodes = GetTrueLocationCodes(model.stockCode.Trim(), model.areaCode, locationCodes, model.type); if (locationTrueCodes.Count == 0) { Log.AlgorInfo("GetLocationByArea_R", "货位扩展表中没有数据"); } //else //{ // List locationLog = locationTrueCodes.Select(o => o.CN_S_LOCATION_CODE).ToList(); // Log.AlgorInfo("GetLocationByArea_R", "tn_wm_b_location_ext中货位数据" + string.Join(",", locationLog)); //} if (locationTrueCodes != null && locationTrueCodes.Count != 0) { lstTrueLocation = lstLocation.Join(locationTrueCodes, u => u.CN_S_LOCATION_CODE, d => d.CN_S_LOCATION_CODE, (u, d) => new { u, d }) .Select(o => o.u).ToList(); } //if (lstTrueLocation.Count == 0) //{ // Log.AlgorInfo("GetLocationByArea_R", "lstTrueLocation中没有数据"); //} //else //{ // List locationLog = lstTrueLocation.Select(o => o.CN_S_LOCATION_CODE).ToList(); // Log.AlgorInfo("GetLocationByArea_R", "lstTrueLocation中货位数据" + string.Join(",", locationLog)); //} return lstTrueLocation; } /// /// 获得货位扩展表中可用的货位 /// /// /// /// private List GetTrueLocationCodes(string stockCode, string areaCode, List locationCodes, int type) { List lstTrueLocations = new List(); switch (type) { case 1://仓库 只根据仓库编号获得可用货位 lstTrueLocations = CreateDAL().GetLocationCodeExtListBy(stockCode, areaCode, null, "入库"); break; case 2://库区 根据货位编码集合 in 查询关系型数据库中的扩展货位表数据 lstTrueLocations = CreateDAL().GetLocationCodeExtListBy(stockCode, areaCode, null, "入库"); break; case 3://货位 根据单个货位编码 = 查询关系型数据库中的扩展货位表数据 lstTrueLocations = CreateDAL().GetLocationCodeExtListBy(stockCode, areaCode, locationCodes, "入库"); break; case 4://库区(流离式货架) 根据货位编码集合 in 查询关系型数据库中的扩展货位表数据 lstTrueLocations = CreateDAL().GetLocationCodeExtListBy(stockCode, areaCode, null, "入流离库"); break; case 5://库区(流离式货架) 根据货位编码集合 in 查询关系型数据库中的扩展货位表数据 lstTrueLocations = CreateDAL().GetLocationCodeExtListBy(stockCode, areaCode, locationCodes, "入流离库"); break; } return lstTrueLocations; } #endregion #region 作业区(流离式、平库、立库)入库算法入扣 public InAssignResultEntity InAssign(InAssignEntity model) { //定义返回实体 InAssignResultEntity resultEntity = new InAssignResultEntity(); resultEntity.Msg = ""; Log.AlgorInfo("InAssign", "入库算法参数:" + JsonConvert.SerializeObject(model)); try { #region 传入参数判断 if (model == null) { resultEntity.Success = false; resultEntity.Msg = "参数实体不能为 null !"; return resultEntity; } //判断对象编号不能为空 //if (string.IsNullOrEmpty(model.objectCode)) //{ // resultEntity.Success = false; // resultEntity.Msg = "指定的入作业库对象编号不能为空!"; // return resultEntity; //} //判断传入库区列表不能为空 if (model.lstAreaPrior == null || model.lstAreaPrior.Count == 0) { resultEntity.Success = false; resultEntity.Msg = "指定的入作业库库区列表不能为空!"; return resultEntity; } #endregion //(流离式、平库、立库)标准入库算法 string areaType = CreateDAL().GetAreaTypeByCode(model.lstAreaPrior[0].areaCode.ToString()); if (areaType == Constants.Area_Struc_PingStock || areaType == Constants.Area_Struc_LiStock) { if (model.projectCode == "jxhn") { resultEntity = FlatAreaGetLocationJx(model, model.lstDevice); } else { resultEntity = FlatAreaGetLocation(model, model.lstDevice); } } resultEntity.areaType = areaType; Log.AlgorInfo("InAssign", "入库返回结果:" + JsonConvert.SerializeObject(resultEntity)); return resultEntity; } catch (Exception ex) { Log.AlgorInfo("InAssign", "异常日志:" + ex.Message + ex.StackTrace); resultEntity.Msg = "算法异常," + ex.Message + ex.StackTrace; resultEntity.errCode = "1002"; return resultEntity; } } #endregion #region 作业区 平库入库算法 public InAssignResultEntity FlatAreaGetLocation(InAssignEntity model, List lstDevice) { InAssignResultEntity resultEntity = new InAssignResultEntity(); resultEntity.Success = false; List lstTrueLocation = new List(); List lstTmpLocation = new List(); List lstALR = null; List lstLocation = new List(); List lstJuxingLocation = new List(); List lstLockLItem = new List(); List lstEmptyLocation = new List(); List lstTrueLItem = new List(); List lstAreaPrior = model.lstAreaPrior.OrderBy(o => o.Prior).ToList(); StringBuilder sbDetailError = new StringBuilder(); if (model.projectCode == "ntsd") { foreach (areaPriorClass item in lstAreaPrior) { List lstTask = CreateDAL().GetTaskByAreaCode(item.areaCode); item.Prior = lstTask.Count; } lstAreaPrior = lstAreaPrior.OrderBy(o => o.Prior).ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstAreaPrior数据:" + JsonConvert.SerializeObject(lstAreaPrior)); } #region 从autobom和货位扩展表中获取可用货位集合 //按优先级循环处理库区获取可用货位集合 foreach (areaPriorClass item in lstAreaPrior) { AutoBomStockAreaEntity areaModel = CreateDAL().GetModel(item.areaCode.ToString()); model.stockCode = areaModel.CN_S_STOCK_CODE; resultEntity.isControlQty = areaModel.CN_C_IS_CONTROL_QTY; resultEntity.isControlInv = areaModel.CN_C_IS_INVENTORY; resultEntity.areaCode = item.areaCode; if (model.needCalLock) { model.lockLocation = resultEntity.isControlQty.Equals("Y") ? true : false;//不管控数量时,不锁定目的货位 } //定义传入变量实体 获取可用货位集合 LogicTrue logicModel = new LogicTrue(); logicModel.stockCode = ""; if (string.IsNullOrEmpty(model.logicAreaCode)) { logicModel.type = 2; logicModel.areaCode = item.areaCode; } else { //只支持逻辑分区关联货位、库区 logicModel.areaCode = item.areaCode; lstALR = CreateDAL().GetLocationByLogicArea(model.logicAreaCode, item.areaCode); if (lstALR != null && lstALR.Count > 0) { if (lstALR[0].CN_N_TYPE == 2) { logicModel.type = 2; logicModel.areaCode = item.areaCode; } else if (lstALR[0].CN_N_TYPE == 3) { logicModel.type = 3; logicModel.lstLocationCode = lstALR.Where(o => o.CN_N_TYPE == 3).Select(o => o.CN_S_LOCATION_CODE).ToList(); } } } //获取在autobom中可用货位的集合(去除废弃的货位) Log.AlgorInfo("InAssign-FlatAreaGetLocation", "求可用货位的logicModel参数:" + JsonConvert.SerializeObject(logicModel)); lstLocation = BLLCreator.Create().AutoBomLocationTrue(logicModel); // Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocation:" + JsonConvert.SerializeObject(lstLocation)); //获取在货位扩展表中可用的货位的集合(去除锁定的货位) List locationTrueCodes = BLLCreator.Create().GetTrueLocationCodes(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, logicModel.type, Constants.Area_Struc_PingStock); lstEmptyLocation.AddRange(locationTrueCodes); //获取交集 if (locationTrueCodes != null && locationTrueCodes.Count != 0) { lstTrueLItem = lstLocation.Join(locationTrueCodes, u => u.CN_S_LOCATION_CODE, d => d.CN_S_LOCATION_CODE, (u, d) => new { u, d }) .Select(o => o.u).ToList(); lstTrueLocation.AddRange(lstTrueLItem); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "与monog交集lstTrueLItem:" + JsonConvert.SerializeObject(lstTrueLItem)); if (model.projectCode == "jxhn") { string areaClass = CreateDAL().GetAreaClassByCode(item.areaCode.ToString()); //控制该库区的任务总数阀值 if (areaClass == "高架库") { #region 高架库 //LogicTrue logicT = new LogicTrue(); //logicT.stockCode = ""; //logicT.type = 2; //logicT.areaCode = item.areaCode; //lstJuxingLocation = BLLCreator.Create().AutoBomLocationTrue(logicT); //获取系统配置的巷道最大任务数限制 long maxTaskQty = 0; List list = BLLCreator.Create>().GetList(); ; TN_WM_B_STRATEGY_VALUEEntity strategy = list.Where(o => o.CN_S_CODE == "RoadMaxTask").FirstOrDefault(); if (strategy != null) { if (!string.IsNullOrEmpty(strategy.CN_S_VALUE)) { maxTaskQty = long.Parse(strategy.CN_S_VALUE); } } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "高架库中RoadMaxTask:" + maxTaskQty.ToString()); //获取该库区中所有未执行或执行中的出入库任务 List lstTask = CreateDAL().GetTaskByAreaCode(item.areaCode); List lstRoadTask = new List(); lstRoadTask = lstTrueLItem.GroupBy(o => o.CN_S_ROADWAY).Select(g => (new RoadTask { roadWay = g.Key, taskNum = 0 })).Distinct().ToList(); List lstTmpL = new List(); List lstNewRoadTask = new List(); foreach (RoadTask roadT in lstRoadTask) { lstTmpL = lstLocation.Where(o => o.CN_S_ROADWAY == roadT.roadWay).Select(a => a.CN_S_LOCATION_CODE).ToList(); roadT.taskNum = lstTask.Where(o => lstTmpL.Contains(o.CN_S_START_BIT) || lstTmpL.Contains(o.CN_S_END_BIT)).Count(); if (roadT.taskNum < maxTaskQty) { lstNewRoadTask.Add(roadT); } } if (lstNewRoadTask.Count > 0) { lstNewRoadTask = lstNewRoadTask.OrderBy(o => o.taskNum).ToList(); lstTmpL = lstNewRoadTask.Where(o => o.taskNum == lstNewRoadTask.FirstOrDefault().taskNum).Select(a => a.roadWay).ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstNewRoadTask:" + JsonConvert.SerializeObject(lstNewRoadTask)); lstTrueLItem = lstTrueLItem.Where(o => lstTmpL.Contains(o.CN_S_ROADWAY)).ToList(); } else { lstTrueLItem.Clear(); } #endregion } else if (areaClass == "缓存区") { #region 缓存区 //巷道内有入不能有出 有出不能有入 巷道任务尽量平均分配 // 获取预入库锁定的货位 List locationInLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, null, Constants.Location_State_InLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationInLock数据:" + JsonConvert.SerializeObject(locationInLock)); // 获取预出库锁定的货位 List locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, null, Constants.Location_State_OutLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(locationOutLock)); List lstOutLockRow = locationOutLock.Select(o => o.CN_S_ROW).Distinct().ToList(); lstTrueLItem.RemoveAll(o => lstOutLockRow.Contains(o.CN_S_ROW)); //获取货位所在行的预入库任务数量 List lstTask = new List(); lstTask = lstTrueLItem.Select(o => new RoadTask { roadWay = o.CN_S_ROW, taskNum = 0 }).Distinct().ToList(); foreach (RoadTask roadT in lstTask) { roadT.taskNum = locationInLock.Where(o => o.CN_S_ROW == roadT.roadWay).Count(); } lstTask = lstTask.OrderBy(o => o.taskNum).ToList(); lstTrueLItem = lstTrueLItem.Where(o => o.CN_S_ROW == lstTask.FirstOrDefault().roadWay).ToList(); #endregion } else if (areaClass == "地堆") { #region 地堆 //去除被(异形件)人工绑定阻挡的货位 List lstLocationHasItem = CreateDAL().GetLocationByItemCode("", "", item.areaCode); List lstLocationRowCols = new List(); List lstRows = lstLocationHasItem.Select(o => o.CN_S_ROW).Distinct().ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocationSameItem数据:" + JsonConvert.SerializeObject(lstLocationHasItem)); List tmpTrueItem = new List(); List tmpGreaterItem = new List(); foreach (string sRow in lstRows) { lstLocationRowCols = lstLocationHasItem.Where(o => o.CN_S_ROW == sRow).OrderByDescending(a => int.Parse(a.CN_S_COL)).ToList(); tmpGreaterItem = lstTrueLItem.Where(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) > int.Parse(lstLocationRowCols[0].CN_S_COL)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) < int.Parse(lstLocationRowCols[0].CN_S_COL)); if (tmpGreaterItem.Count > 0) { tmpTrueItem.AddRange(tmpGreaterItem); } } if (tmpTrueItem.Count > 0) { lstTrueLItem = tmpTrueItem; } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); //地堆中只有入库任务,获取预入库锁定的货位 List locationInLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_InLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "去除被(异形件)人工绑定阻挡的货位数据:" + JsonConvert.SerializeObject(locationInLock)); //获取货位所在行的预入库任务数量 List lstTask = new List(); lstTask = lstTrueLItem.Select(o => new RoadTask { roadWay = o.CN_S_ROW, taskNum = 0 }).Distinct().ToList(); foreach (RoadTask roadT in lstTask) { roadT.taskNum = locationInLock.Where(o => o.CN_S_ROW == roadT.roadWay).Count(); } lstTask = lstTask.OrderBy(o => o.taskNum).ToList(); lstTrueLItem = lstTrueLItem.Where(o => o.CN_S_ROW == lstTask.FirstOrDefault().roadWay).ToList(); #endregion } } else if (model.projectCode == "ys001") { #region 宇寿算法定制代码 //获取该托盘中的物料信息 List lstOriginalMST = BLLCreator.Create>().GetList(new { CN_S_TRAY_CODE = model.objectCode }); string itemCode = ""; if (lstOriginalMST.Count > 0) { itemCode = lstOriginalMST[0].CN_S_ITEM_CODE; } //获取预出库锁定的货位 List locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_OutLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(lstLockLItem)); foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationOutLock) { lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW && o.CN_S_COL == lEntity.CN_S_COL); } List locationCheckLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, null, Constants.Location_Check_Lock); Log.AlgorInfo("OutAssign-FlatAreaOutLocation", "locationCheckLock数据:" + JsonConvert.SerializeObject(locationCheckLock)); foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationCheckLock) { lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW && o.CN_S_COL == lEntity.CN_S_COL); } List locationCarryLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, null, Constants.Location_Carry_Lock); Log.AlgorInfo("OutAssign-FlatAreaOutLocation", "locationCarryLock数据:" + JsonConvert.SerializeObject(locationCarryLock)); foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationCarryLock) { lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW && o.CN_S_COL == lEntity.CN_S_COL); } List lstLocationHasItem = CreateDAL().GetLocationByItemCode("", "", item.areaCode); List lstLocationHasItemOrder = new List(); List lstLocationRowCols = new List(); List lstItemCols = lstLocationHasItem.GroupBy(a => new { a.CN_S_ROW, a.CN_S_COL }).Select(o => new AutoBomLocationAbbreEntity { CN_S_ROW = o.Key.CN_S_ROW, CN_S_COL = o.Key.CN_S_COL }).ToList(); foreach (AutoBomLocationAbbreEntity itemC in lstItemCols) { lstLocationHasItemOrder = lstLocationHasItem.Where(o => o.CN_S_ROW == itemC.CN_S_ROW && o.CN_S_COL == itemC.CN_S_COL).OrderByDescending(a => int.Parse(a.CN_S_FLOOR)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == itemC.CN_S_ROW && o.CN_S_COL == itemC.CN_S_COL && int.Parse(o.CN_S_FLOOR) < int.Parse(lstLocationHasItemOrder[0].CN_S_FLOOR)); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "去除阻挡后的lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); //查找该库区中已存放该物料的货位 List lstLocationSameItem = CreateDAL().GetLocationByItemCode(itemCode, item.areaCode); //查找该库区中即将要存放该物料的货位 List lstTaskSameItem = CreateDAL().GetInTaskLocationByItemCode(itemCode, item.areaCode); if (lstTaskSameItem.Count > 0) { lstLocationSameItem.AddRange(lstTaskSameItem); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocationSameItem数据:" + JsonConvert.SerializeObject(lstLocationSameItem)); List tmpTrueItem = new List(); lstItemCols = lstLocationSameItem.GroupBy(a => new { a.CN_S_ROW, a.CN_S_COL }).Select(o => new AutoBomLocationAbbreEntity { CN_S_ROW = o.Key.CN_S_ROW, CN_S_COL = o.Key.CN_S_COL }).ToList(); foreach (AutoBomLocationAbbreEntity lEntity in lstItemCols) { tmpTrueItem.AddRange(lstTrueLItem.Where(o => o.CN_S_COL == lEntity.CN_S_COL && o.CN_S_ROW == lEntity.CN_S_ROW).ToList()); } if (tmpTrueItem.Count > 0) { lstTrueLItem = tmpTrueItem; } else { //判断库区中是否有未使用的空列 List lstEmptyCol = lstTrueLItem.GroupBy(a => new { a.CN_S_ROW, a.CN_S_COL }).Select(o => new AutoBomLocationAbbreEntity { CN_S_ROW = o.Key.CN_S_ROW, CN_S_COL = o.Key.CN_S_COL }).ToList(); foreach (AutoBomLocationAbbreEntity aEntity in lstEmptyCol) { if (lstTrueLItem.Where(o => o.CN_S_ROW == aEntity.CN_S_ROW && o.CN_S_COL == aEntity.CN_S_COL).Count() == lstLocation.Where(o => o.CN_S_ROW == aEntity.CN_S_ROW && o.CN_S_COL == aEntity.CN_S_COL).Count()) { tmpTrueItem.AddRange(lstTrueLItem.Where(o => o.CN_S_ROW == aEntity.CN_S_ROW && o.CN_S_COL == aEntity.CN_S_COL).ToList()); } } if (tmpTrueItem.Count > 0) { lstTrueLItem = tmpTrueItem; } } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); #endregion } else if (model.projectCode == "qzhk") { #region 衢州华凯算法定制代码 string areaClass = CreateDAL().GetAreaClassByCode(item.areaCode.ToString()); if (areaClass == "密集型") { string itemCode = model.itemCode; //获取预出库锁定的货位 List locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_OutLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(lstLockLItem)); foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationOutLock) { lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW); } List lstLocationHasItem = CreateDAL().GetLocationByItemCode("", "", item.areaCode); List lstLocationHasItemOrder = new List(); List lstLocationRowCols = new List(); List lstItemRows = lstLocationHasItem.GroupBy(a => new { a.CN_S_ROW, }).Select(o => new AutoBomLocationAbbreEntity { CN_S_ROW = o.Key.CN_S_ROW }).ToList(); foreach (AutoBomLocationAbbreEntity itemC in lstItemRows) { lstLocationHasItemOrder = lstLocationHasItem.Where(o => o.CN_S_ROW == itemC.CN_S_ROW).OrderByDescending(a => int.Parse(a.CN_S_COL)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == itemC.CN_S_ROW && int.Parse(o.CN_S_COL) < int.Parse(lstLocationHasItemOrder[0].CN_S_COL)); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "去除阻挡后的lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); //查找该库区中已存放该物料的货位 List lstLocationSameItem = CreateDAL().GetLocationByItemCodeAndLotNo(model.itemCode, model.lotNo, item.areaCode); //查找该库区中即将要存放该物料的货位 List lstTaskSameItem = CreateDAL().GetInTaskLocationByItemCodeAndLotNo(model.itemCode, model.lotNo, item.areaCode); if (lstTaskSameItem.Count > 0) { lstLocationSameItem.AddRange(lstTaskSameItem); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocationSameItem数据:" + JsonConvert.SerializeObject(lstLocationSameItem)); List tmpTrueItem = new List(); lstItemRows = lstLocationSameItem.GroupBy(a => new { a.CN_S_ROW }).Select(o => new AutoBomLocationAbbreEntity { CN_S_ROW = o.Key.CN_S_ROW }).ToList(); foreach (AutoBomLocationAbbreEntity lEntity in lstItemRows) { tmpTrueItem.AddRange(lstTrueLItem.Where(o => o.CN_S_ROW == lEntity.CN_S_ROW).ToList()); } if (tmpTrueItem.Count > 0) { lstTrueLItem = tmpTrueItem; } else { //判断库区中是否有未使用的空列 List lstEmptyCol = lstTrueLItem.GroupBy(a => new { a.CN_S_ROW }).Select(o => new AutoBomLocationAbbreEntity { CN_S_ROW = o.Key.CN_S_ROW }).ToList(); foreach (AutoBomLocationAbbreEntity aEntity in lstEmptyCol) { if (lstTrueLItem.Where(o => o.CN_S_ROW == aEntity.CN_S_ROW).Count() == lstLocation.Where(o => o.CN_S_ROW == aEntity.CN_S_ROW).Count()) { tmpTrueItem.AddRange(lstTrueLItem.Where(o => o.CN_S_ROW == aEntity.CN_S_ROW).ToList()); } } if (tmpTrueItem.Count > 0) { lstTrueLItem = tmpTrueItem; } } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); } #endregion } else if (model.projectCode == "masym") { #region 马鞍山粤美算法定制代码 List lstStrategy = CreateDAL().GetStrateListByAreaOrStock("", resultEntity.areaCode, "入库"); //获取预出库锁定的货位 if (lstStrategy.Select(o => o.CN_S_CODE).ToList().Contains("FirstInLastOut")) { List locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_OutLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(lstLockLItem)); List lstOutLockRows = locationOutLock.GroupBy(a => new { a.CN_S_ROW }).Select(o => new TN_WM_LOCATIONCODE_EXT_Entity { CN_S_ROW = o.Key.CN_S_ROW }).ToList(); foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in lstOutLockRows) { lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "去除预出库锁定后的lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); List lstLocationHasItem = CreateDAL().GetLocationByItemCode("", "", item.areaCode); List lstLocationInlock = CreateDAL().GetLocationByInLockYM("", "", item.areaCode); if (lstLocationInlock.Count > 0) { lstLocationHasItem.AddRange(lstLocationInlock); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocationHasItem数据:" + JsonConvert.SerializeObject(lstLocationHasItem)); List lstLocationHasItemOrder = new List(); List lstItemRows = lstLocationHasItem.GroupBy(a => new { a.CN_S_ROW }).Select(o => o.Key.CN_S_ROW ).ToList(); foreach (string itemC in lstItemRows) { lstLocationHasItemOrder = lstLocationHasItem.Where(o => o.CN_S_ROW == itemC).OrderByDescending(a => int.Parse(a.CN_S_COL)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == itemC && int.Parse(o.CN_S_COL) < int.Parse(lstLocationHasItemOrder[0].CN_S_COL)); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "去除阻挡后的lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); } #endregion } else if (model.projectCode == "ntsd") { #region 南通定制算法代码 List lstStrategy = new List(); lstStrategy = CreateDAL().GetStrateListByAreaOrStock("", resultEntity.areaCode, "入库"); if (lstStrategy.Select(o => o.CN_S_CODE).ToList().Contains("FirstInLastOut")) { //获取该托盘中的物料信息 List lstOriginalMST = BLLCreator.Create>().GetList(new { CN_S_TRAY_CODE = model.objectCode }); string itemCode = ""; if (lstOriginalMST.Count > 0) { itemCode = lstOriginalMST[0].CN_S_ITEM_CODE; } //获取预出库锁定的货位,预出库锁定货位所在列的其他货位(同层)还可以使用 //List locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_OutLock); //Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(lstLockLItem)); //foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationOutLock) //{ // lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW && o.CN_S_COL != lEntity.CN_S_COL); //} //获取预出库锁定的货位,预出库锁定货位所在排不能入 List locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_OutLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(lstLockLItem)); foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationOutLock) { lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW); } //获取预入库锁定的货位,预入库锁定货位所在列的其他货位(同层)还可以使用 List locationInLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_InLock); //Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationInLock数据:" + JsonConvert.SerializeObject(locationInLock)); //foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationInLock) //{ // lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW && o.CN_S_COL != lEntity.CN_S_COL); //} Log.AlgorInfo("InAssign-FlatAreaGetLocation", "去除锁定数据后stTrueLItem:" + JsonConvert.SerializeObject(lstTrueLItem)); //查找该库区中已存放该物料的货位 List lstLocationSameItem = CreateDAL().GetLocationByItemCode(itemCode, item.areaCode); //查找该库区中即将要存放该物料的货位 List lstTaskSameItem = CreateDAL().GetInTaskLocationByItemCode(itemCode, item.areaCode); if (lstTaskSameItem.Count > 0) { lstLocationSameItem.AddRange(lstTaskSameItem); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocationSameItem数据:" + JsonConvert.SerializeObject(lstLocationSameItem)); //获取该库区中已存放该物料或即将存放该物料的排 //List lstSameItemRow = lstLocationSameItem.Select(o => o.CN_S_ROW).Distinct().ToList(); List lstEmptyRow = lstTrueLItem.Select(o => o.CN_S_ROW).Distinct().ToList(); //获取符合条件的排lstSameItemRow中任务最少的一个排并且该排中有位置可以放 List lstRowTask = new List(); foreach (string sRow in lstEmptyRow) { rowTaskNT rowT = new rowTaskNT(); rowT.row = sRow; rowT.taskNum = locationInLock.Where(o => o.CN_S_ROW == sRow).Count() + locationOutLock.Where(o => o.CN_S_ROW == sRow).Count(); rowT.GoodLocationNum = lstLocationSameItem.Where(o => o.CN_S_ROW == sRow).Count(); lstRowTask.Add(rowT); } lstRowTask = lstRowTask.OrderBy(o => o.taskNum).ThenBy(a => a.GoodLocationNum).ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstRowTask数据:" + JsonConvert.SerializeObject(lstRowTask)); if (lstRowTask.Count > 0) { lstTrueLItem = lstTrueLItem.Where(a => a.CN_S_ROW == lstRowTask.FirstOrDefault().row).ToList(); } else { lstTrueLItem.Clear(); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); } #endregion } else if (model.projectCode == "tzlj") { #region 泰州隆基定制算法代码 List lstStrategy = new List(); lstStrategy = CreateDAL().GetStrateListByAreaOrStock("", resultEntity.areaCode, "入库"); List locationOutLock = new List(); List locationInLock = new List(); if (lstStrategy.Select(o => o.CN_S_CODE).ToList().Contains("FirstInLastOutLj")) { //获取预出库锁定的货位,预出库锁定货位所在排不能入 locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_OutLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(locationOutLock)); foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationOutLock) { lstTrueLItem.RemoveAll(o => o.CN_S_COL == lEntity.CN_S_COL); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "去除锁定数据后stTrueLItem:" + JsonConvert.SerializeObject(lstTrueLItem)); //获取预入库锁定的货位 locationInLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_InLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationInLock数据:" + JsonConvert.SerializeObject(locationInLock)); } if (lstStrategy.Select(o => o.CN_S_CODE).ToList().Contains("AdjoinColNoTask")) { foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationOutLock) { lstTrueLItem.RemoveAll(o => int.Parse(o.CN_S_COL) == int.Parse(lEntity.CN_S_COL) + 1); lstTrueLItem.RemoveAll(o => int.Parse(o.CN_S_COL) == int.Parse(lEntity.CN_S_COL) - 1); } foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationInLock) { lstTrueLItem.RemoveAll(o => int.Parse(o.CN_S_COL) == int.Parse(lEntity.CN_S_COL) + 1); lstTrueLItem.RemoveAll(o => int.Parse(o.CN_S_COL) == int.Parse(lEntity.CN_S_COL) - 1); } } if (lstStrategy.Select(o => o.CN_S_CODE).ToList().Contains("FirstInLastOutLj")) { //查找该库区中已存放该物料的货位 List lstLocationSameItem = CreateDAL().GetLocationByItemCode(model.itemCode, item.areaCode); ////查找该库区中即将要存放该物料的货位 //List lstTaskSameItem = CreateDAL().GetInTaskLocationByItemCode(itemCode, item.areaCode); //if (lstTaskSameItem.Count > 0) //{ // lstLocationSameItem.AddRange(lstTaskSameItem); //} //Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocationSameItem数据:" + JsonConvert.SerializeObject(lstLocationSameItem)); //获取该库区中已存放该物料或即将存放该物料的排 // List lstSameItemRow = lstLocationSameItem.Select(o => o.CN_S_ROW).Distinct().ToList(); //List tmpTrueItem = new List(); List lstEmptyCol = lstTrueLItem.Select(o => o.CN_S_COL).Distinct().ToList(); //获取符合条件的排lstSameItemRow中任务最少的一个列并且该排中有位置可以放 List lstColTask = new List(); foreach (string sCol in lstEmptyCol) { rowTaskNT rowT = new rowTaskNT(); rowT.row = sCol; rowT.taskNum = locationInLock.Where(o => o.CN_S_COL == sCol).Count(); rowT.GoodLocationNum = lstLocationSameItem.Where(o => o.CN_S_COL == sCol).Count(); lstColTask.Add(rowT); } lstColTask = lstColTask.OrderBy(o => o.taskNum).ThenBy(a => a.GoodLocationNum).ToList(); //获取符合条件的排lstSameItemRow中任务最少的一个排并且该排中有位置可以放 Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstRowTask数据:" + JsonConvert.SerializeObject(lstColTask)); if (lstColTask.Count > 0) { lstTrueLItem = lstTrueLItem.Where(a => a.CN_S_COL == lstColTask.FirstOrDefault().row).ToList(); } else { lstTrueLItem.Clear(); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); } #endregion } else if (model.projectCode == "hcbh") { #region 杭叉钣焊算法定制代码 //获取预出库锁定的货位 List locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_OutLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(locationOutLock)); List lstOutLockRow = locationOutLock.Select(o => o.CN_S_ROW).Distinct().ToList(); lstTrueLItem.RemoveAll(o => lstOutLockRow.Contains(o.CN_S_ROW)); //获取预出库锁定的货位 List locationInLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_InLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationInLock数据:" + JsonConvert.SerializeObject(locationOutLock)); List lstInLockRow = locationInLock.Select(o => o.CN_S_ROW).Distinct().ToList(); List lstLocationLock = new List(); foreach (string sRow in lstInLockRow) { lstLocationLock = locationInLock.Where(o => o.CN_S_ROW == sRow).OrderByDescending(a => int.Parse(a.CN_S_COL)).ToList(); // tmpGreaterItem = lstTrueLItem.Where(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) > int.Parse(lstLocationRowCols[0].CN_S_COL)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) < int.Parse(lstLocationLock[0].CN_S_COL)); } //去除因被阻挡而不能入的货位 List lstLocationHasItem = CreateDAL().GetLocationByItemCode("", "", item.areaCode); List lstLocationRowCols = new List(); List lstRows = lstLocationHasItem.Select(o => o.CN_S_ROW).Distinct().ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocationSameItem数据:" + JsonConvert.SerializeObject(lstLocationHasItem)); // List tmpTrueItem = new List(); // List tmpGreaterItem = new List(); foreach (string sRow in lstRows) { lstLocationRowCols = lstLocationHasItem.Where(o => o.CN_S_ROW == sRow).OrderByDescending(a => int.Parse(a.CN_S_COL)).ToList(); //tmpGreaterItem = lstTrueLItem.Where(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) > int.Parse(lstLocationRowCols[0].CN_S_COL)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) < int.Parse(lstLocationRowCols[0].CN_S_COL)); //if (tmpGreaterItem.Count > 0) //{ // tmpTrueItem.AddRange(tmpGreaterItem); //} } //if (tmpTrueItem.Count > 0) //{ // lstTrueLItem = tmpTrueItem; //} Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); #endregion } if (lstTrueLItem.Count > 0) { if (resultEntity.isControlQty == "N") { //该库区中的货位如果为不管控数量,则对所有货位平均分配入库任务 resultEntity = AverageLocation(lstTrueLItem, model.lockLocation, resultEntity.isControlQty); } else { //根据入库策略计算货位 resultEntity = CalLocationByStraty(resultEntity, lstDevice, lstTrueLItem, lstLocation, lstLockLItem, model.lockLocation); } } if (resultEntity.Success) { break; } } if (!resultEntity.Success) { if (lstEmptyLocation == null || lstEmptyLocation.Count == 0) { resultEntity.Success = false; resultEntity.Msg = "空货位不足"; resultEntity.errCode = "1001"; return resultEntity; } if (lstTrueLocation == null || lstTrueLocation.Count == 0) { resultEntity.Success = false; resultEntity.Msg = "两表关联后无可用的货位!请根据ID在日志管理中查询详细原因"; resultEntity.errCode = "1001"; return resultEntity; } resultEntity.Success = false; resultEntity.Msg = "启用策略后无可用的货位"; resultEntity.errCode = "1001"; return resultEntity; } #endregion return resultEntity; } public InAssignResultEntity FlatAreaGetLocationJx(InAssignEntity model, List lstDevice) { InAssignResultEntity resultEntity = new InAssignResultEntity(); resultEntity.Success = false; List lstTrueLocation = new List(); List lstTmpLocation = new List(); List lstALR = null; List lstLocation = new List(); List lstTaskTrueLItem = new List(); List lstTaskTrueLItemR = new List(); //指定计算后返回的实体 List location_roadray = new List(); List lstLockLItem = new List(); List lstEmptyLocation = new List(); List lstTrueLItem = new List(); List lstAreaPrior = model.lstAreaPrior.OrderBy(o => o.Prior).ToList(); StringBuilder sbDetailError = new StringBuilder(); #region 从autobom和货位扩展表中获取可用货位集合 //按优先级循环处理库区获取可用货位集合 foreach (areaPriorClass item in lstAreaPrior) { AutoBomStockAreaEntity areaModel = CreateDAL().GetModel(item.areaCode.ToString()); model.stockCode = areaModel.CN_S_STOCK_CODE; resultEntity.isControlQty = areaModel.CN_C_IS_CONTROL_QTY; resultEntity.isControlInv = areaModel.CN_C_IS_INVENTORY; resultEntity.areaCode = item.areaCode; if (model.needCalLock) { model.lockLocation = resultEntity.isControlQty.Equals("Y") ? true : false;//不管控数量时,不锁定目的货位 } //定义传入变量实体 获取可用货位集合 LogicTrue logicModel = new LogicTrue(); logicModel.stockCode = ""; logicModel.type = 2; logicModel.areaCode = item.areaCode; //获取在autobom中可用货位的集合(去除废弃的货位) Log.AlgorInfo("InAssign-FlatAreaGetLocation", "求可用货位的logicModel参数:" + JsonConvert.SerializeObject(logicModel)); lstLocation = BLLCreator.Create().AutoBomLocationTrue(logicModel); //获取在货位扩展表中可用的货位的集合(去除锁定的货位) List locationTrueCodes = BLLCreator.Create().GetTrueLocationCodes(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, logicModel.type, Constants.Area_Struc_PingStock); lstEmptyLocation.AddRange(locationTrueCodes); //获取交集 if (locationTrueCodes != null && locationTrueCodes.Count != 0) { lstTrueLItem = lstLocation.Join(locationTrueCodes, u => u.CN_S_LOCATION_CODE, d => d.CN_S_LOCATION_CODE, (u, d) => new { u, d }) .Select(o => o.u).ToList(); lstTrueLocation.AddRange(lstTrueLItem); } string areaClass = CreateDAL().GetAreaClassByCode(item.areaCode.ToString()); //控制该库区的任务总数阀值 if (areaClass == "高架库") { #region 高架库 //获取系统配置的巷道最大任务数限制 long maxTaskQty = 0; List list = BLLCreator.Create>().GetList(); ; TN_WM_B_STRATEGY_VALUEEntity strategy = list.Where(o => o.CN_S_CODE == "RoadMaxTask").FirstOrDefault(); if (strategy != null) { if (!string.IsNullOrEmpty(strategy.CN_S_VALUE)) { maxTaskQty = long.Parse(strategy.CN_S_VALUE); } } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "高架库中RoadMaxTask:" + maxTaskQty.ToString()); //获取该库区中所有未执行或执行中的入库任务 List lstTask = CreateDAL().GetTaskByAreaCodeJX(item.areaCode); List lstRowTask = new List(); List lstTmpRowTask = new List(); List lstTmpL = new List(); List lstTmpLR = new List(); List lstRowTaskNum = new List(); lstRowTask = lstTrueLItem.GroupBy(o => o.CN_S_ROW).Select(g => (new RowTask { row = g.Key, taskNum = 0 })).Distinct().ToList(); foreach (RowTask rowT in lstRowTask) { lstTmpL = lstLocation.Where(o => o.CN_S_ROW == rowT.row).Select(a => a.CN_S_LOCATION_CODE).ToList(); rowT.roadWay = lstTrueLItem.Where(o => o.CN_S_ROW == rowT.row).FirstOrDefault().CN_S_ROADWAY; rowT.taskNum = lstTask.Where(o => lstTmpL.Contains(o.CN_S_END_BIT)).Count(); } Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstRowTask:" + JsonConvert.SerializeObject(lstRowTask)); lstALR = CreateDAL().GetLocationByLogicAreaJX(model.logicAreaCode, item.areaCode); foreach (AutoBomLocationAbbreEntity abbEntity in lstTrueLItem) { AutoBomAreaLocation_REntity rEntity = lstALR.Where(o => o.CN_S_LOCATION_CODE == abbEntity.CN_S_LOCATION_CODE).FirstOrDefault(); if (rEntity != null) { //暂用CN_C_LAST_TRAY 记录该货位的档位 abbEntity.CN_C_LAST_TRAY = rEntity.CN_S_AREA_CODE; } } // Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstTrueLItem:" + JsonConvert.SerializeObject(lstTrueLItem)); List lstRoadTask = new List(); lstRoadTask = lstTrueLItem.GroupBy(o => o.CN_S_ROADWAY).Select(g => (new RoadTask { roadWay = g.Key, taskNum = 0 })).Distinct().ToList(); List lstNewRoadTask = new List(); foreach (RoadTask roadT in lstRoadTask) { lstTmpL = lstLocation.Where(o => o.CN_S_ROADWAY == roadT.roadWay).Select(a => a.CN_S_LOCATION_CODE).ToList(); roadT.taskNum = lstTask.Where(o => lstTmpL.Contains(o.CN_S_END_BIT)).Count(); if (roadT.taskNum < maxTaskQty) { lstNewRoadTask.Add(roadT); } } if (lstNewRoadTask.Count > 0) { Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstNewRoadTask:" + JsonConvert.SerializeObject(lstNewRoadTask)); List lstTaskNum = lstNewRoadTask.Select(o => o.taskNum).Distinct().ToList(); lstTaskNum.Sort(); foreach (int num in lstTaskNum) { //优先计算任务数量少的巷道 lstTmpL = lstNewRoadTask.Where(o => o.taskNum == num).Select(a => a.roadWay).ToList(); lstTaskTrueLItem = lstTrueLItem.Where(o => lstTmpL.Contains(o.CN_S_ROADWAY)).ToList(); //再计算排任务数量少的货位 lstTmpRowTask = lstRowTask.Where(o => lstTmpL.Contains(o.roadWay)).ToList(); lstTmpRowTask = lstTmpRowTask.OrderBy(o => o.taskNum).ToList(); lstRowTaskNum = lstTmpRowTask.Select(o => o.taskNum).Distinct().ToList(); lstRowTaskNum.Sort(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstRowTaskNum:" + JsonConvert.SerializeObject(lstRowTaskNum)); foreach (int num1 in lstRowTaskNum) { lstTmpLR = lstTmpRowTask.Where(o => o.taskNum == num1).Select(a => a.row).ToList(); lstTaskTrueLItemR = lstTaskTrueLItem.Where(o => lstTmpLR.Contains(o.CN_S_ROW)).ToList(); var v = lstTaskTrueLItemR.GroupBy(x => x.CN_S_ROW).Select(g => (new { row = g.Key, qty = g.Count() })).OrderByDescending(o => o.qty); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "排可用货位排序后数据:" + JsonConvert.SerializeObject(v)); //倒叙排列后的排 循环 foreach (var row in v) { location_roadray = lstTaskTrueLItemR.Where(o => o.CN_S_ROW == row.row).ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "location_roadray:" + JsonConvert.SerializeObject(location_roadray)); if (location_roadray.Where(o => o.CN_C_LAST_TRAY == model.logicAreaCode).Count() > 0) { location_roadray = location_roadray.Where(o => o.CN_C_LAST_TRAY == model.logicAreaCode).ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "有符合逻辑分区的数据"); } else { #region 针对低档位的物料如果货位不足可继续寻找高档位存放 if (model.logicAreaCode == "1") { if (location_roadray.Where(o => o.CN_C_LAST_TRAY == "2").Count() > 0) { location_roadray = location_roadray.Where(o => o.CN_C_LAST_TRAY == "2").ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "传入1档,1档不足寻找2档"); } else { if (location_roadray.Where(o => o.CN_C_LAST_TRAY == "3").Count() > 0) { location_roadray = location_roadray.Where(o => o.CN_C_LAST_TRAY == "3").ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "传入1档,2档不足寻找3档"); } else { continue; } } } else if (model.logicAreaCode == "2") { if (location_roadray.Where(o => o.CN_C_LAST_TRAY == "3").Count() > 0) { location_roadray = location_roadray.Where(o => o.CN_C_LAST_TRAY == "3").ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "传入2档,2档不足寻找3档"); } else { continue; } } else { continue; } #endregion } if (location_roadray.Count() > 0) { resultEntity = CalLocationByStraty(resultEntity, lstDevice, location_roadray, lstLocation, lstLockLItem, model.lockLocation); } if (resultEntity.Success) { break; } } if (resultEntity.Success) { break; } } if (resultEntity.Success) { break; } } } #endregion } else if (areaClass == "缓存区") { #region 缓存区 //巷道内有入不能有出 有出不能有入 巷道任务尽量平均分配 // 获取预入库锁定的货位 List locationInLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, null, Constants.Location_State_InLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationInLock数据:" + JsonConvert.SerializeObject(locationInLock)); // 获取预出库锁定的货位 List locationOutLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, null, Constants.Location_State_OutLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "locationOutLock数据:" + JsonConvert.SerializeObject(locationOutLock)); List lstOutLockRow = locationOutLock.Select(o => o.CN_S_ROW).Distinct().ToList(); lstTrueLItem.RemoveAll(o => lstOutLockRow.Contains(o.CN_S_ROW)); //获取货位所在行的预入库任务数量 List lstTask = new List(); lstTask = lstTrueLItem.Select(o => new RoadTask { roadWay = o.CN_S_ROW, taskNum = 0 }).Distinct().ToList(); foreach (RoadTask roadT in lstTask) { roadT.taskNum = locationInLock.Where(o => o.CN_S_ROW == roadT.roadWay).Count(); } lstTask = lstTask.OrderBy(o => o.taskNum).ToList(); lstTrueLItem = lstTrueLItem.Where(o => o.CN_S_ROW == lstTask.FirstOrDefault().roadWay).ToList(); if (lstTrueLItem.Count() > 0) { resultEntity = CalLocationByStraty(resultEntity, lstDevice, lstTrueLItem, lstLocation, lstLockLItem, model.lockLocation); } #endregion } else if (areaClass == "地堆") { #region 地堆 //去除被(异形件)人工绑定阻挡的货位 List locationInLock = CreateDAL().GetLockLocationByState(model.stockCode.Trim(), item.areaCode, logicModel.lstLocationCode, Constants.Location_State_InLock); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "预入库锁定的货位的货位数据:" + JsonConvert.SerializeObject(locationInLock)); List lstLocationHasItem = CreateDAL().GetLocationByItemCode("", "", item.areaCode); List lstLocationRowCols = new List(); List lstRows = lstLocationHasItem.Select(o => o.CN_S_ROW).Distinct().ToList(); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstLocationSameItem数据:" + JsonConvert.SerializeObject(lstLocationHasItem)); foreach (TN_WM_LOCATIONCODE_EXT_Entity lEntity in locationInLock) { lstTrueLItem.RemoveAll(o => o.CN_S_ROW == lEntity.CN_S_ROW); if (lstRows.Contains(lEntity.CN_S_ROW)) { lstRows.Remove(lEntity.CN_S_ROW); } } List tmpTrueItem = new List(); List tmpGreaterItem = new List(); #region 查询该库区配置的入库策略及优先级 List lstStrategy = new List(); lstStrategy = CreateDAL().GetStrateListByAreaOrStock("", resultEntity.areaCode, "入库"); List lstStrate = lstStrategy.OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList(); #endregion foreach (string sRow in lstRows) { if (lstStrate.Contains("InSmallToBig")) { lstLocationRowCols = lstLocationHasItem.Where(o => o.CN_S_ROW == sRow).OrderByDescending(a => int.Parse(a.CN_S_COL)).ToList(); tmpGreaterItem = lstTrueLItem.Where(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) > int.Parse(lstLocationRowCols[0].CN_S_COL)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) < int.Parse(lstLocationRowCols[0].CN_S_COL)); if (tmpGreaterItem.Count > 0) { tmpTrueItem.AddRange(tmpGreaterItem); } } else if (lstStrate.Contains("InBigToSmall")) { lstLocationRowCols = lstLocationHasItem.Where(o => o.CN_S_ROW == sRow).OrderBy(a => int.Parse(a.CN_S_COL)).ToList(); tmpGreaterItem = lstTrueLItem.Where(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) < int.Parse(lstLocationRowCols[0].CN_S_COL)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) > int.Parse(lstLocationRowCols[0].CN_S_COL)); if (tmpGreaterItem.Count > 0) { tmpTrueItem.AddRange(tmpGreaterItem); } } else { lstLocationRowCols = lstLocationHasItem.Where(o => o.CN_S_ROW == sRow).OrderByDescending(a => int.Parse(a.CN_S_COL)).ToList(); tmpGreaterItem = lstTrueLItem.Where(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) > int.Parse(lstLocationRowCols[0].CN_S_COL)).ToList(); lstTrueLItem.RemoveAll(o => o.CN_S_ROW == sRow && int.Parse(o.CN_S_COL) < int.Parse(lstLocationRowCols[0].CN_S_COL)); if (tmpGreaterItem.Count > 0) { tmpTrueItem.AddRange(tmpGreaterItem); } } } if (tmpTrueItem.Count > 0) { lstTrueLItem = tmpTrueItem; } // Log.AlgorInfo("InAssign-FlatAreaGetLocation", "lstTrueLItem数据:" + JsonConvert.SerializeObject(lstTrueLItem)); if (lstTrueLItem.Count() > 0) { resultEntity = CalLocationByStraty(resultEntity, lstDevice, lstTrueLItem, lstLocation, lstLockLItem, model.lockLocation); } #endregion } else { if (lstTrueLItem.Count() > 0) { resultEntity = CalLocationByStraty(resultEntity, lstDevice, lstTrueLItem, lstLocation, lstLockLItem, model.lockLocation); } } if (resultEntity.Success) { break; } } if (!resultEntity.Success) { if (lstEmptyLocation == null || lstEmptyLocation.Count == 0) { resultEntity.Success = false; resultEntity.Msg = "空货位不足"; resultEntity.errCode = "1001"; return resultEntity; } if (lstTrueLocation == null || lstTrueLocation.Count == 0) { resultEntity.Success = false; resultEntity.Msg = "两表关联后无可用的货位!请根据ID在日志管理中查询详细原因"; resultEntity.errCode = "1001"; return resultEntity; } resultEntity.Success = false; resultEntity.Msg = "启用策略后无可用的货位"; resultEntity.errCode = "1001"; return resultEntity; } #endregion return resultEntity; } /// /// 获取平库立库货架中最近的一个可用货位 /// /// /// /// /// private InAssignResultEntity CalLocationByStraty(InAssignResultEntity resultEntity, List lstDevice, List lstTrueLocation, List lstAllLocation, List lstLockLItem, bool lockLocation) { List lstTmp_Location = new List(); string deviceCode = string.Empty; #region 查询该库区配置的入库策略及优先级 List lstStrategy = new List(); lstStrategy = CreateDAL().GetStrateListByAreaOrStock("", resultEntity.areaCode, "入库"); List lstStrate = lstStrategy.OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList(); #endregion // Log.AlgorInfo("InAssign-FlatAreaGetLocation", "循环前lstTrueLocation数据:" + JsonConvert.SerializeObject(lstTrueLocation)); lstTmp_Location = CalculateLocByStegy(ref lstDevice, lstTrueLocation, lstAllLocation, lstLockLItem, lstStrate, out deviceCode); Log.AlgorInfo("InAssign-FlatAreaGetLocation", "循环后lstTmp_Location数据:" + JsonConvert.SerializeObject(lstTmp_Location)); if (lstTmp_Location == null || lstTmp_Location.Count == 0) { resultEntity.Success = false; resultEntity.Msg = "库区有空货位但启用算法策略后计算出货位不足"; return resultEntity; } AutoBomLocationAbbreEntity at_l_Entity = lstTmp_Location[0]; if (lockLocation) { #region 锁定入库货位 SqlExecuteResult result = CreateDAL().UpdateLocationState(at_l_Entity.CN_S_LOCATION_CODE, Constants.Location_State_InLock, "入库", null); Log.AlgorInfo("InAssign-CalLocationByStraty", at_l_Entity.CN_S_LOCATION_CODE + "货位更改为预入库锁定,锁定结果:" + result.Success + result.Row); if (result.Success && result.Row > 0) { resultEntity.Success = true; resultEntity.Msg = ""; resultEntity.locationCode = at_l_Entity.CN_S_LOCATION_CODE; resultEntity.stockCode = at_l_Entity.CN_S_STOCK_CODE; if (!string.IsNullOrEmpty(deviceCode)) { //增加设备任务数 lstDevice = lstDevice.Select(o => { o.taskNum = o.deviceCode == deviceCode ? o.taskNum + 1 : o.taskNum; return o; }).ToList(); } } else { resultEntity.Success = false; resultEntity.errCode = "1002"; resultEntity.Msg = "锁定货位状态失败"; } #endregion } else { resultEntity.Success = true; resultEntity.Msg = ""; resultEntity.locationCode = at_l_Entity.CN_S_LOCATION_CODE; resultEntity.stockCode = at_l_Entity.CN_S_STOCK_CODE; } return resultEntity; } /// /// 根据入库策略筛选符合条件的货位 /// /// /// /// /// /// public List CalculateLocByStegy(ref List lstDevice, List lstLocation, List lstAllLocation, List lstLockLItem, List lstStrate, out string deviceCode) { List lstFilterLoc = lstLocation; List lstTmp = new List(); deviceCode = string.Empty; AlgorTacticsCommon Trctics = new AlgorTacticsCommon(); foreach (string stegy in lstStrate) { //逐个策略进行计算 switch (stegy) { case "EquipmentBalance": //设备均衡 lstFilterLoc = Trctics.EquipmentBalance(lstDevice, lstFilterLoc, out deviceCode); break; case "RoadWayBalance": //巷道均衡 lstFilterLoc = Trctics.RoadWayBalance(lstFilterLoc); break; case "NearByRoadWay": //巷道由近及远 lstFilterLoc = Trctics.RoadWayBalance(lstFilterLoc); break; case "NearbyBalance": //就近原则 lstFilterLoc = Trctics.NearbyBalance(lstFilterLoc); break; case "FarbyBalance": //就远原则 lstFilterLoc = Trctics.FarbyBalance(lstFilterLoc); break; case "NearbyBalanceRow": //排就近原则 lstFilterLoc = Trctics.NearbyBalanceRow(lstFilterLoc); break; case "FirstInLastOut": //宇寿 南通 巨星 先进后出 lstFilterLoc = Trctics.FirstInLastOut(lstFilterLoc, lstAllLocation, lstLockLItem, lstStrate); break; case "FirstInLastOutLj": //隆基先进后出 lstFilterLoc = Trctics.FirstInLastOutLj(lstFilterLoc, lstAllLocation, lstLockLItem, lstStrate); break; case "SyncEmptyFirst": //隆基 优先计算先被同步为空的货位 List lstTrueLocations = CreateDAL().GetLocationCreateTime(lstFilterLoc.Select(o => o.CN_S_LOCATION_CODE).ToList()); lstFilterLoc = lstFilterLoc.Join(lstTrueLocations, u => u.CN_S_LOCATION_CODE, d => d.CN_S_LOCATION_CODE, (u, d) => new { u, d }) .Select(o => new AutoBomLocationAbbreEntity { CN_S_LOCATION_CODE = o.u.CN_S_LOCATION_CODE, CN_S_STOCK_CODE = o.u.CN_S_STOCK_CODE, CN_T_CREATE = o.d.CN_T_CREATE }).ToList(); lstFilterLoc = lstLocation.OrderBy(o => o.CN_T_CREATE).ToList(); ; break; } } return lstFilterLoc; } /// /// 根据平均入库策略获取可用货位 /// /// /// /// /// private InAssignResultEntity AverageLocation(List lstTrueLocation, bool lockLocation, string isControlQty) { InAssignResultEntity resultEntity = new InAssignResultEntity(); //策略实体 AlgorTacticsCommon Trctics = new AlgorTacticsCommon(); AutoBomLocationAbbreEntity at_l_Entity = Trctics.AverageBalance(lstTrueLocation); bool result = CreateDAL().UpdateLocationTaskQty(at_l_Entity.CN_S_LOCATION_CODE, at_l_Entity.CN_N_INTASK_QTY + 1); if (result) { resultEntity.Success = true; resultEntity.Msg = ""; resultEntity.locationCode = at_l_Entity.CN_S_LOCATION_CODE; resultEntity.stockCode = at_l_Entity.CN_S_STOCK_CODE; } else { resultEntity.Success = false; resultEntity.Msg = "计算货位失败-更新入库任务数失败"; } return resultEntity; } #endregion } }