| 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 | 
| { | 
|     /// <summary> | 
|     /// 自动移库处理类 | 
|     /// </summary> | 
|     public class AutoMoveLocationHandler | 
|     { | 
|         private static object ojb = new object(); | 
|         private static object ojb_AddTask = new object(); | 
|         /// <summary> | 
|         /// 获取当前正在执行的闲时移库任务 | 
|         /// </summary> | 
|         /// <param name="mod"></param> | 
|         /// <returns></returns> | 
|         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; | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 是否前面存在未结束的移库任务 | 
|         /// </summary> | 
|         /// <param name="mod"></param> | 
|         /// <param name="areaCode"></param> | 
|         /// <returns></returns> | 
|         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; | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 高库位去合适库位的移库 | 
|         /// </summary> | 
|         /// <param name="areaCode"></param> | 
|         /// <param name="freeTimeMoveLocationTask"></param> | 
|         /// <returns></returns> | 
|         public static bool DoForHighLocation(dbModel mod, string areaCode, Wms_FreeTimeMoveLocationTask freeTimeMoveLocationTask) | 
|         { | 
|             /* | 
|              * 1、分区处理 | 
|              * 2、优先按照库位高度匹配进行移库 | 
|              * 3、其次按照库存平衡进行移库 | 
|              */ | 
|             //策略1:读取高度不匹配的数据 | 
|             List<vvBase_ProductPosition> _prdListForIsInMoreHighPosition = new List<vvBase_ProductPosition>(); | 
|   | 
|             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; | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 库存平衡的移库 | 
|         /// </summary> | 
|         /// <param name="areaCode"></param> | 
|         /// <param name="freeTimeMoveLocationTask"></param> | 
|         /// <returns></returns> | 
|         public static bool DoForAutoBalance(dbModel mod, string areaCode, Wms_FreeTimeMoveLocationTask freeTimeMoveLocationTask) | 
|         { | 
|             /* | 
|              * 1、分区处理 | 
|              * 2、优先按照库位高度匹配进行移库 | 
|              * 3、其次按照库存平衡进行移库 | 
|              */ | 
|             //策略2:按照库存平衡进行移库 | 
|             List<vvBase_ProductPosition> _prdList = new List<vvBase_ProductPosition>(); | 
|   | 
|             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; | 
|         } | 
|   | 
|         /// <summary> | 
|         ///  | 
|         /// </summary> | 
|         /// <param name="filter_shelveCode">按照排数过滤</param> | 
|         /// <param name="autoMoveLocationReason"></param> | 
|         /// <param name="freeTimeMoveLocationTask"></param> | 
|         /// <param name="mod"></param> | 
|         /// <param name="username"></param> | 
|         /// <param name="source_position"></param> | 
|         /// <param name="areaCode"></param> | 
|         /// <param name="prod_position"></param> | 
|         /// <param name="store"></param> | 
|         /// <returns></returns> | 
|         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.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 | 
|             } | 
|         } | 
|     } | 
| } |