using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using wcftest.BussinessExtension.Common; using wcftest.EnumDefine; using wcftest.orm; namespace wcftest.BussinessExtension.Handle { /// /// 自动移库处理类 /// public class AutoMoveLocationHandler { private static object ojb = new object(); private static object ojb_AddTask = new object(); /// /// 获取当前正在执行的闲时移库任务 /// /// /// public static Wms_FreeTimeMoveLocationTask GetCurExcuteFreeTimeMoveLocationTask(dbModel mod) { lock (ojb) { var queryMoveStatus = (int)MoveStatusEnum.执行中; var task = mod.Wms_FreeTimeMoveLocationTask.Where(x => x.MoveStatus == queryMoveStatus).FirstOrDefault(); if (task != null) { //判断这个是否已经到期了 if (task.StartTime == null) { throw new Exception("任务已执行中,但是开始时间为NULL"); } var startTime = Convert.ToDateTime(task.StartTime); int runTime = Convert.ToInt32(task.RunTime); var planEndTime = startTime.AddMinutes(runTime);//计划结束日期 if (planEndTime <= DateTime.Now) { //强制结束 task.LastModifier = "调度系统"; task.LastModifyTime = DateTime.Now; task.Remark = "自动到期结束"; MoveStatusEnum moveStatusEnum = MoveStatusEnum.执行完毕; task.MoveStatus = (int)moveStatusEnum; task.MoveStatusName = moveStatusEnum.ToString(); var endTime = DateTime.Now; task.EndTime = endTime; //计算持续时长(分钟) if (task.StartTime != null) { TimeSpan ts = ((DateTime)endTime - (DateTime)task.StartTime); task.ActualTime = Convert.ToInt32(ts.TotalMinutes); } //计算已完成数量 var count = mod.Wms_FreeTimeMoveLocationTaskDetails.Where(x => x.MainFreeMoveId == task.ID).Count(); task.FinishQuantity = count; mod.SaveChanges(); return null; } else {//还不到时间,继续执行 return task; } } return null; } } /// /// 是否前面存在未结束的移库任务 /// /// /// /// public static bool IsNeedCreateNewMoveTask(dbModel mod, string areaCode) { var list = BussinessExtension.GetDoingTaskList(mod, Convert.ToInt32(areaCode), TaskTypeEnum.移库); if (list != null && list.Count > 0) { return false; } return true; } /// /// 高库位去合适库位的移库 /// /// /// /// public static bool DoForHighLocation(dbModel mod, string areaCode, Wms_FreeTimeMoveLocationTask freeTimeMoveLocationTask) { /* * 1、分区处理 * 2、优先按照库位高度匹配进行移库 * 3、其次按照库存平衡进行移库 */ //策略1:读取高度不匹配的数据 List _prdListForIsInMoreHighPosition = new List(); var queryIsLocked = (int)IsLockedEnum.未锁定; var queryIsFreeze = (int)IsFreezeEnum.有货; var queryEnable = (int)usable.可用; var prdList = mod.vvBase_ProductPosition.Where(x => x.PositionName != SysGlole.PositionName_SHZCQ && x.IsInMoreHighPosition == 1 && x.AreaCode == areaCode && x.IsLocked == queryIsLocked && x.IsFreeze == queryIsFreeze).ToList(); if (prdList == null || prdList.Count() == 0) { return false; } //排除掉有任务占用的情况,优化 【EditBy shaocx,2022-09-21】 _prdListForIsInMoreHighPosition = BussinessExtension.FilterPositionTakeDoingTask(prdList, mod, Convert.ToInt32(areaCode)); if (_prdListForIsInMoreHighPosition.Count > 0) {//进行移库 //只取一个进行移库 foreach (var item in _prdListForIsInMoreHighPosition) { var prod_position = mod.Base_ProductPosition.Where(x => x.ProductPosition_Id == item.ProductPosition_Id).FirstOrDefault(); Base_Position source_position = mod.Base_Position.Where(x => x.PositionName == prod_position.PositionName).FirstOrDefault(); if (source_position.Enable != queryEnable) { continue;//不可用库位,就直接跳过 } var validateExistPlaceTaskList = FreeTimeMoveLocationTaskHandler.ValidateExistPlaceTaskList(mod, freeTimeMoveLocationTask, source_position.PositionName); if (validateExistPlaceTaskList == false) { continue;//已经执行过了,就直接跳过 } var result = AddTaskForMoveStore("", AutoMoveLocationReasonEnum.高库位去合适库位, freeTimeMoveLocationTask, mod, "", source_position, Convert.ToInt32(areaCode), prod_position, item); if (result) { return true;//执行成功了,就直接结束,返回true } } } return false; } /// /// 库存平衡的移库 /// /// /// /// public static bool DoForAutoBalance(dbModel mod, string areaCode, Wms_FreeTimeMoveLocationTask freeTimeMoveLocationTask) { /* * 1、分区处理 * 2、优先按照库位高度匹配进行移库 * 3、其次按照库存平衡进行移库 */ //策略2:按照库存平衡进行移库 List _prdList = new List(); var queryIsLocked = (int)IsLockedEnum.未锁定; var queryIsFreeze = (int)IsFreezeEnum.有货; var queryEnable = (int)usable.可用; var prdList = mod.vvBase_ProductPosition.Where(x => x.PositionName != SysGlole.PositionName_SHZCQ && x.AreaCode == areaCode && x.IsLocked == queryIsLocked && x.IsFreeze == queryIsFreeze).ToList(); if (prdList == null || prdList.Count() == 0) { return false; } //排除掉有任务占用的情况,优化 【EditBy shaocx,2022-09-21】 _prdList = BussinessExtension.FilterPositionTakeDoingTask(prdList, mod, Convert.ToInt32(areaCode)); if (_prdList.Count > 0) {//进行移库 var _prdList_01 = _prdList.Where(x => x.ShelveCode == "01").ToList(); var _prdList_02 = _prdList.Where(x => x.ShelveCode == "02").ToList(); int _prdList_01_Count = _prdList_01 == null ? 0 : _prdList_01.Count; int _prdList_02_Count = _prdList_02 == null ? 0 : _prdList_02.Count; string sourceShelveCode = "", toShelveCode = ""; if (_prdList_01_Count > _prdList_02_Count) { sourceShelveCode = "01"; toShelveCode = "02"; } else if (_prdList_01_Count < _prdList_02_Count) { sourceShelveCode = "02"; toShelveCode = "01"; } else { return false; } if (!string.IsNullOrEmpty(sourceShelveCode)) { //只取一个进行移库 foreach (var item in _prdList) { var prod_position = mod.Base_ProductPosition.Where(x => x.ProductPosition_Id == item.ProductPosition_Id).FirstOrDefault(); Base_Position source_position = mod.Base_Position.Where(x => x.PositionName == prod_position.PositionName).FirstOrDefault(); if (source_position.Enable != queryEnable) { continue;//不可用库位,就直接跳过 } var validateExistPlaceTaskList = FreeTimeMoveLocationTaskHandler.ValidateExistPlaceTaskList(mod, freeTimeMoveLocationTask, source_position.PositionName); if (validateExistPlaceTaskList == false) { continue;//已经执行过了,就直接跳过 } var result = AddTaskForMoveStore(toShelveCode, AutoMoveLocationReasonEnum.库存平衡, freeTimeMoveLocationTask, mod, "", source_position, Convert.ToInt32(areaCode), prod_position, item); if (result) { return true;//执行成功了,就直接结束,返回true } } } } return false; } /// /// /// /// 按照排数过滤 /// /// /// /// /// /// /// /// /// private static bool AddTaskForMoveStore(string filter_shelveCode, AutoMoveLocationReasonEnum autoMoveLocationReason, Wms_FreeTimeMoveLocationTask freeTimeMoveLocationTask, dbModel mod, string username, Base_Position source_position, int areaCode, Base_ProductPosition prod_position, vvBase_ProductPosition store) { lock (ojb_AddTask) { var sourcePlace = store.PositionName.Substring(2); var findEmptyReason = ""; bool isInMoreHighPosition = false; //返回格式: 格式: 01-03-01 if (store.PhysicsHeight == null) { return false;//说明没有光电检测高度 } #region 事务 using (var trans = mod.Database.BeginTransaction()) { try { var toplace = FindEmptyLocationHandler.findStorage(mod, filter_shelveCode, false, ref isInMoreHighPosition, ref findEmptyReason, Convert.ToInt32(areaCode), Convert.ToInt32(prod_position.PlateType), Convert.ToInt32(store.PhysicsHeight));//分配库位 if (isInMoreHighPosition) {//表示入了不匹配自己高度的库位,找的是更高的库位,不处理 return false; } if (string.IsNullOrEmpty(toplace)) {//未找到库位 return false; } var validateExistPlaceTaskList = FreeTimeMoveLocationTaskHandler.ValidateExistPlaceTaskList(mod, freeTimeMoveLocationTask, areaCode + "-" + toplace); if (validateExistPlaceTaskList == false) { return false;//已经执行过了,就直接跳过 } #region 写入任务表 Task_Queue addTask = new Task_Queue(); addTask.BillCode = "移库";//来源单号 addTask.TaskType = ((int)TaskTypeEnum.移库).ToString(); addTask.PlateType = prod_position.PlateType;//器具种类-大托盘小托盘 addTask.PlateCode = prod_position.PlateCode;//母托盘编号 addTask.Bill_Id = 0;// 单据id addTask.OrderNumber = 0;//任务执行优先级 addTask.TaskStatus = "未下发";//任务状态 addTask.FromPositionName = sourcePlace;//起始地址 addTask.ToPositionName = toplace;//目标地址给空返回测量高度后重新写入 addTask.Direction = areaCode == 1 ? "2" : "4";//出库不需要托盘高度 addTask.DoCount = areaCode;//库区 addTask.CreateDate = DateTime.Now; addTask.Creator = "系统"; addTask.UserProduct_Id = 1007;//账套id 老谢bug mod.Task_Queue.Add(addTask); int result = mod.SaveChanges(); if (result == 0) { throw new Exception("新增任务表失败"); } #endregion #region 写入 闲时移库任务明细表 Wms_FreeTimeMoveLocationTaskDetails details = new Wms_FreeTimeMoveLocationTaskDetails() { AreaCode = areaCode.ToString(), SoucePlace = areaCode + "-" + sourcePlace, ToPlace = areaCode + "-" + toplace, CreateTime = DateTime.Now, Creator = "", LastModifier = "", LastModifyTime = DateTime.Now, MainFreeMoveId = freeTimeMoveLocationTask.ID, MoveRemark = autoMoveLocationReason.ToString(), Remark = "初始", Task_Id = addTask.Task_Id }; mod.Wms_FreeTimeMoveLocationTaskDetails.Add(details); #endregion //添加日志 SystemHelper.addOperation(mod, username, "移库:从" + sourcePlace + "到" + toplace, "移库,库区:" + areaCode); //锁定库位(源库位+目标库位) var query_toplace = areaCode + "-" + toplace; Base_Position to_position = mod.Base_Position.Where(x => x.PositionName == query_toplace).FirstOrDefault(); to_position.IsLocked = 1;//找到空库位时,库位锁定! to_position.Remark = "闲时移库-找到空库位时,库位锁定!"; //to_position.IsFreeze = 1; to_position.IsFreeze = (int)IsFreezeEnum.有货; source_position.IsLocked = 1;//找到空库位时,库位锁定! source_position.Remark = "闲时移库-找到空库位时,库位锁定!"; //更新闲时移库表的次数 if (freeTimeMoveLocationTask.FinishQuantity == null) { freeTimeMoveLocationTask.FinishQuantity = 1; } else { freeTimeMoveLocationTask.FinishQuantity = Convert.ToInt32(freeTimeMoveLocationTask.FinishQuantity) + 1; } result = mod.SaveChanges(); if (result == 0) { throw new Exception("保存失败"); } trans.Commit(); return true; } catch (Exception ex) { trans.Rollback(); throw ex; } } #endregion } } } }