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