using HH.Redis.ReisModel;
|
using HH.WMS.BLL;
|
using HH.WMS.BLL.Algorithm;
|
using HH.WMS.BLL.Basic;
|
using HH.WMS.BLL.External;
|
using HH.WMS.BLL.InStock;
|
using HH.WMS.BLL.MoveStock;
|
using HH.WMS.BLL.SysMgr;
|
using HH.WMS.Common;
|
using HH.WMS.Common.Algorithm;
|
using HH.WMS.Common.External;
|
using HH.WMS.DAL;
|
using HH.WMS.DAL.Basic;
|
using HH.WMS.Entitys;
|
using HH.WMS.Entitys.Basic;
|
using HH.WMS.Entitys.Entitys;
|
using HH.WMS.Entitys.External;
|
using HH.WMS.Entitys.MoveStock;
|
using HH.WMS.TaskService.Dto;
|
using Newtonsoft.Json;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
|
namespace HH.WMS.TaskService.Jobs
|
{
|
/// <summary>
|
/// 移库
|
/// </summary>
|
public class CallMaterialJob
|
{
|
private readonly LockDto _lockDto = new LockDto { IsLock = false };
|
|
public void Run()
|
{
|
var logPara = LogType.LogPara("叫料任务");
|
if (_lockDto.IsLock)
|
{
|
Log.Detail(logPara, "当前叫料任务正在被锁定,还存在未执行结束的任务:" + _lockDto.TaskNo);
|
return;
|
}
|
|
var callMaterialJobDto = new CallMaterialJobDto();
|
HandleCallMaterial(ref callMaterialJobDto, logPara);
|
if (!callMaterialJobDto.BasisResponse.Success)
|
RollbackTask(ref callMaterialJobDto, logPara);
|
|
_lockDto.Unlock();
|
}
|
|
private void HandleCallMaterial(ref CallMaterialJobDto callMaterialJobDto, LogPara logPara)
|
{
|
GetCallMaterialTask(ref callMaterialJobDto, logPara);
|
if (!callMaterialJobDto.BasisResponse.Success)
|
{
|
callMaterialJobDto.Normal();
|
return;
|
}
|
|
CalculateStartBit(ref callMaterialJobDto, logPara);
|
if (!callMaterialJobDto.BasisResponse.Success)
|
return;
|
|
MoveOutLocation(ref callMaterialJobDto, logPara);
|
if (!callMaterialJobDto.BasisResponse.Success)
|
return;
|
|
|
}
|
|
//获取移库管理中未执行的数据,只取一条,且将状态变为执行中
|
private void GetCallMaterialTask(ref CallMaterialJobDto callMaterialJobDto, LogPara logPara)
|
{
|
callMaterialJobDto.CallMaterialMst = BLLCreator.Create<CallMaterialTaskBLL>().GetMst();
|
|
if (callMaterialJobDto.CallMaterialMst == null)
|
{
|
callMaterialJobDto.Error("当前没有需要执行的叫料任务!", logPara);
|
return;
|
}
|
|
if (callMaterialJobDto.CallMaterialMst.qty <= callMaterialJobDto.CallMaterialMst.CN_F_QUANTITY)
|
{
|
BLLCreator.Create<MoveStockTaskBLL>().UpdateMstState(callMaterialJobDto.CallMaterialMst.CN_GUID, "已完成", null, logPara);
|
return;
|
}
|
//根据叫料终点获取叫料对应的库区
|
string callAreas = GetAreaByWorkBit(callMaterialJobDto.CallMaterialMst.workBit, ref callMaterialJobDto);
|
|
if(string.IsNullOrEmpty(callAreas))
|
{
|
callMaterialJobDto.Error("该叫料任务工作站点找不到对应的叫料库区!", logPara);
|
return;
|
}
|
//检查当前起始库区、结束库区没有未执行、执行中的任务
|
|
var taskList = BLLCreator.Create<TN_WM_TASKBLL>().GetTaskByAreaCodeList(callAreas);
|
if (taskList.Any())
|
{
|
callMaterialJobDto.Error("当前库区:" + callAreas + " 存在未完成的任务:" + LogDescribe.Content(taskList), logPara);
|
return;
|
}
|
|
BLLCreator.Create<CallMaterialTaskBLL>().UpdateMstState(callMaterialJobDto.CallMaterialMst.CN_GUID, "执行中", null, logPara);
|
_lockDto.Lock(callMaterialJobDto.CallMaterialMst.CN_GUID);
|
}
|
|
private string GetAreaByWorkBit(string workBit, ref CallMaterialJobDto callMaterialJobDto)
|
{
|
StringBuilder strAreaCodes = new StringBuilder();
|
List<AutoBomStockAreaEntity> areaModel = BLLCreator.Create<TN_AB_B_STOCK_AREABLL>().GetAreaByManyClass("中间库,混装区");
|
string workFloor = string.Empty;
|
if (workBit.IndexOf("F1") > 0)
|
{
|
workFloor = "F1";
|
}
|
else if (workBit.IndexOf("F2") > 0)
|
{
|
workFloor = "F2";
|
}
|
else if (workBit.IndexOf("F3") > 0)
|
{
|
workFloor = "F3";
|
}
|
List<areaPriorClass> lstArea = new List<areaPriorClass>();
|
foreach (AutoBomStockAreaEntity entity in areaModel)
|
{
|
if (entity.CN_S_AREA_CODE.IndexOf(workFloor) > 0 && entity.CN_S_AREA_CODE.IndexOf("ZJK")>0)
|
{
|
strAreaCodes.Append(entity.CN_S_AREA_CODE);
|
strAreaCodes.Append(",");
|
|
}
|
if (entity.CN_S_AREA_CODE.IndexOf(workFloor) > 0 && entity.CN_S_AREA_CODE.IndexOf("HZ") > 0)
|
{
|
strAreaCodes.Append(entity.CN_S_AREA_CODE);
|
strAreaCodes.Append(",");
|
}
|
areaPriorClass areaClass = new areaPriorClass();
|
areaClass.areaCode = entity.CN_S_AREA_CODE;
|
areaClass.Prior = 1;
|
lstArea.Add(areaClass);
|
callMaterialJobDto.StockCode = entity.CN_S_STOCK_CODE;
|
}
|
foreach (AutoBomStockAreaEntity entity in areaModel)
|
{
|
|
if (entity.CN_S_AREA_CODE.IndexOf(workFloor) > 0 && entity.CN_S_AREA_CODE.IndexOf("HZ") > 0)
|
{
|
strAreaCodes.Append(entity.CN_S_AREA_CODE);
|
strAreaCodes.Append(",");
|
}
|
areaPriorClass areaClass = new areaPriorClass();
|
areaClass.areaCode = entity.CN_S_AREA_CODE;
|
areaClass.Prior = 1;
|
lstArea.Add(areaClass);
|
}
|
strAreaCodes.Length = strAreaCodes.Length - 1;
|
callMaterialJobDto.lstArea = lstArea;
|
return strAreaCodes.ToString(); ;
|
}
|
|
//计算起点货位
|
private void CalculateStartBit(ref CallMaterialJobDto callMaterialJobDto, LogPara logPara)
|
{
|
|
//调用出库算法,获取待出去托盘
|
OutAssignEnitty oAe = new OutAssignEnitty()
|
{
|
projectCode = "ys001",
|
lstAreaPrior = callMaterialJobDto.lstArea,
|
stockCode = callMaterialJobDto.StockCode,
|
itemCode = callMaterialJobDto.CallMaterialMst.itemCode,
|
traySpec = "",
|
itemQty = callMaterialJobDto.CallMaterialMst.qty - callMaterialJobDto.CallMaterialMst.CN_F_QUANTITY,
|
lockLocation = true//是否需要锁定货位
|
};
|
Log.Detail(logPara, "叫料起点货位算法,参数为:" + JsonConvert.SerializeObject(oAe));
|
OutAssignResultEntity oaEresult = BLLCreator.Create<Out_AlgorBLL>().OutAssign(oAe);
|
if (!oaEresult.Success)
|
{
|
callMaterialJobDto.Error("叫料起点货位计算失败!" + oaEresult.Msg, logPara);
|
return ;//货位获取失败!
|
}
|
callMaterialJobDto.StartLocation = oaEresult.locationCode;
|
}
|
|
//移动货位(移出同排同列外面的货位)
|
private void MoveOutLocation(ref CallMaterialJobDto callMaterialJobDto, LogPara logPara)
|
{
|
var msg = "";
|
|
//获取当前货位所在列外面有几个满货位
|
var locationExt = BLLCreator.Create<DapperBLL<TN_WM_LOCATION_EXTEntity>>().GetSingleEntity(new { CN_S_LOCATION_CODE = callMaterialJobDto.StartLocation });
|
if (locationExt == null)
|
{
|
callMaterialJobDto.Error("当前算法计算的起始货位码不正确,未在货位扩展表中找到数据!", logPara);
|
return;
|
}
|
Log.Detail(logPara, "当前货位信息:" + LogDescribe.Content(locationExt));
|
|
var curFloor = Convert.ToInt32(locationExt.CN_S_FLOOR);
|
var locations = BLLCreator.Create<DapperBLL<TN_WM_LOCATION_EXTEntity>>().GetList(new { CN_S_COL = locationExt.CN_S_COL, CN_S_ROW = locationExt.CN_S_ROW }).Where(w => Convert.ToInt32(w.CN_S_FLOOR) > curFloor).OrderByDescending(e => e.CN_S_FLOOR);
|
Log.Detail(logPara, "同排同列且在当前货位外层的货位集合," + LogDescribe.Content(locations.ToList()));
|
|
var startLocations = new List<string>();
|
var endLocations = new List<string>();
|
var trayCodes = new List<string>();
|
var isAllow = true;
|
//var okList = new List<OkTask>();
|
|
if (!locations.Any())
|
{
|
Log.Detail(logPara, "当前货位的外层没有阻碍!");
|
callMaterialJobDto.Normal();
|
return;
|
}
|
|
foreach (var location in locations)
|
{
|
if (isAllow)
|
{
|
if (Convert.ToInt32(location.CN_S_FLOOR) > curFloor)
|
{
|
if (location.CN_S_USE_STATE.Equals("满") && location.CN_S_LOCATION_STATE.Equals("正常"))
|
{
|
startLocations.Add(location.CN_S_LOCATION_CODE);
|
|
var trayLocation = BLLCreator.Create<DapperBLL<TN_WM_B_TRAY_LOCATIONEntity>>().GetSingleEntity(new { CN_S_LOCATION_CODE = location.CN_S_LOCATION_CODE });
|
Log.Detail(logPara, LogDescribe.Content(trayLocation));
|
|
if (trayLocation == null)
|
{
|
isAllow = false;
|
}
|
else
|
{
|
trayCodes.Add(trayLocation.CN_S_TRAY_CODE);
|
}
|
|
//调用入库算法,获取空货位
|
List<areaPriorClass> lstTmpArea = new List<areaPriorClass>();
|
lstTmpArea.Add(new areaPriorClass { areaCode = location.CN_S_AREA_CODE.Trim(), Prior = 1 });
|
|
InAssignEntity iAe = new InAssignEntity()
|
{
|
lstAreaPrior = lstTmpArea,
|
logicAreaCode = "",
|
objectCode = trayLocation.CN_S_TRAY_CODE,
|
projectCode = "ys001",
|
lockLocation = true//是否需要锁定货位
|
};
|
iAe.lstDevice = null;
|
Log.Detail(logPara, "调用入库算法参数:" + JsonConvert.SerializeObject(iAe));
|
InAssignResultEntity irEresult = BLLCreator.Create<In_AlgorBLL>().InAssign(iAe);
|
Log.Detail(logPara, "调用入库算法结果:" + (irEresult.Success ? "成功" : ("失败," + irEresult.Msg)) + ",计算的货位:" + irEresult.locationCode);
|
if (!irEresult.Success)
|
{
|
isAllow = false;
|
msg = irEresult.Msg;
|
}
|
else
|
{
|
endLocations.Add(irEresult.locationCode);
|
}
|
}
|
}
|
}
|
}
|
//调用入库算法
|
if (isAllow)
|
{
|
if (startLocations.Count > 0)
|
{
|
List<InWorkAreaEntity> inWorkAreaEntitys = new List<InWorkAreaEntity>();
|
for (int i = 0; i < startLocations.Count; i++)
|
{
|
inWorkAreaEntitys.Add(new InWorkAreaEntity
|
{
|
isTransport = "Y",
|
startBit = startLocations[i],
|
endBit = endLocations[i],
|
projectCode = "ys001",
|
trayCode = trayCodes[i],
|
data = null
|
});
|
}
|
Log.Detail(logPara, "调用入库算法,参数:" + JsonConvert.SerializeObject(inWorkAreaEntitys));
|
|
var result = BLLCreator.Create<WmsApiBaseBLL>().InWorkArea(inWorkAreaEntitys, logPara);
|
if (!result.success)
|
{
|
foreach (var taskPara in inWorkAreaEntitys)
|
{
|
BLLCreator.Create<DapperBLL<TN_WM_LOCATION_EXTEntity>>().Update(new { CN_S_LOCATION_STATE = "正常", CN_S_USE_STATE = "满" }, new { CN_S_LOCATION_CODE = taskPara.startBit });
|
BLLCreator.Create<DapperBLL<TN_WM_LOCATION_EXTEntity>>().Update(new { CN_S_LOCATION_STATE = "正常", CN_S_USE_STATE = "空" }, new { CN_S_LOCATION_CODE = taskPara.endBit });
|
}
|
|
Log.Detail(logPara, "执行入库方法失败!回滚所有任务,原因:" + result.errMsg + ",参数:" + JsonConvert.SerializeObject(result.okList));
|
msg = result.errMsg;
|
callMaterialJobDto.Error("执行入库方法失败!原因:" + result.errMsg, logPara);
|
return;
|
}
|
else
|
{
|
callMaterialJobDto.OkTasks = result.okList;
|
//moveStockJobDto.MoveOutLocationResultData = okList;
|
|
//向AMS下达任务
|
var sendParamList = new List<TN_WM_TRANSPORT_TASKEntity>();
|
|
// var parentGuid = callMaterialJobDto.CallMaterialMst.CN_GUID;
|
result.okList.ForEach(m =>
|
{
|
sendParamList.Add(new TN_WM_TRANSPORT_TASKEntity
|
{
|
CN_S_TASK_NO = m.taskNo,
|
CN_S_START_BIT = m.startBit,
|
CN_S_END_BIT = m.endBit,
|
CN_N_PRIORITY = m.priority,
|
CN_S_CIR_OBJ_CODE = m.trayCode,
|
CN_S_PROJECT_CODE = "",
|
CN_T_CREATE = ""
|
});
|
// BLLCreator.Create<MoveStockTaskBLL>().AddDtl(parentGuid, m.taskNo, "入库", 0, null);
|
});
|
|
//调用AMS,下达出库指令
|
var amsResult = BLLCreator.Create<HH.WMS.BLL.SysMgr.TN_WM_TASKBLL>().SendTask(sendParamList, "入库");
|
Log.Detail(logPara, "调用AMS,下达出库指令!参数:" + LogDescribe.Content(sendParamList) + ",结果:" + (amsResult.Success ? "成功!" : ("失败," + amsResult.Exception.Message)));
|
}
|
}
|
}
|
else
|
{
|
if (endLocations.Any())
|
{
|
//起点
|
//foreach (var startLocation in startLocations)
|
//{
|
// //解锁被锁定的货位 CreateDAL<TN_WM_TASKDAL>().UpdateState(endLocation, "正常", "空", "预出库锁定", null);
|
// BLLCreator.Create<DapperBLL<TN_WM_LOCATION_EXTEntity>>().Update(new { CN_S_LOCATION_STATE = "正常", CN_S_USE_STATE = "满" }, new { CN_S_LOCATION_CODE = startLocation });
|
//}
|
|
foreach (var endLocation in endLocations)
|
{
|
//解锁被锁定的货位 CreateDAL<TN_WM_TASKDAL>().UpdateState(endLocation, "正常", "空", "预出库锁定", null);
|
BLLCreator.Create<DapperBLL<TN_WM_LOCATION_EXTEntity>>().Update(new { CN_S_LOCATION_STATE = "正常", CN_S_USE_STATE = "空" }, new { CN_S_LOCATION_CODE = callMaterialJobDto.StartLocation });
|
Log.Detail(logPara, "解锁被锁定的货位: " + endLocation + "为正常,空!");
|
}
|
}
|
callMaterialJobDto.Error("不能移动货位,原因:" + msg, logPara);
|
return;
|
}
|
|
return;
|
}
|
|
|
|
|
//回滚
|
private void RollbackTask(ref CallMaterialJobDto callMaterialJobDto, LogPara logPara)
|
{
|
if (!string.IsNullOrEmpty(callMaterialJobDto.StartLocation))
|
BLLCreator.Create<DapperBLL<TN_WM_LOCATION_EXTEntity>>().Update(new { CN_S_LOCATION_STATE = "正常" },
|
new { CN_S_LOCATION_CODE = callMaterialJobDto.StartLocation });
|
|
if (callMaterialJobDto.OkTasks.Any())
|
{
|
Log.Detail(logPara, "待回滚的任务:" + JsonConvert.SerializeObject(callMaterialJobDto.OkTasks));
|
callMaterialJobDto.OkTasks.ForEach(t =>
|
{
|
BLLCreator.Create<WmsApiBaseBLL>().ExecuteState(t.taskNo, "取消", logPara);
|
});
|
}
|
|
BLLCreator.Create<DapperBLL<TN_WM_MOVE_STOCK_TASK_MSTEntity>>().Update(new { CN_S_STATE = "执行失败", CN_S_RESULT = callMaterialJobDto.BasisResponse.Message }, new { callMaterialJobDto.CallMaterialMst.CN_GUID });
|
}
|
}
|
}
|