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