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 { /// /// 移库 /// 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().GetMst(); if (callMaterialJobDto.CallMaterialMst == null) { callMaterialJobDto.Error("当前没有需要执行的叫料任务!", logPara); return; } if (callMaterialJobDto.CallMaterialMst.qty <= callMaterialJobDto.CallMaterialMst.CN_F_QUANTITY) { BLLCreator.Create().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().GetTaskByAreaCodeList(callAreas); if (taskList.Any()) { callMaterialJobDto.Error("当前库区:" + callAreas + " 存在未完成的任务:" + LogDescribe.Content(taskList), logPara); return; } BLLCreator.Create().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 areaModel = BLLCreator.Create().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 lstArea = new List(); 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().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>().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>().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(); var endLocations = new List(); var trayCodes = new List(); var isAllow = true; //var okList = new List(); 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>().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 lstTmpArea = new List(); 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().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 inWorkAreaEntitys = new List(); 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().InWorkArea(inWorkAreaEntitys, logPara); if (!result.success) { foreach (var taskPara in inWorkAreaEntitys) { BLLCreator.Create>().Update(new { CN_S_LOCATION_STATE = "正常", CN_S_USE_STATE = "满" }, new { CN_S_LOCATION_CODE = taskPara.startBit }); BLLCreator.Create>().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(); // 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().AddDtl(parentGuid, m.taskNo, "入库", 0, null); }); //调用AMS,下达出库指令 var amsResult = BLLCreator.Create().SendTask(sendParamList, "入库"); Log.Detail(logPara, "调用AMS,下达出库指令!参数:" + LogDescribe.Content(sendParamList) + ",结果:" + (amsResult.Success ? "成功!" : ("失败," + amsResult.Exception.Message))); } } } else { if (endLocations.Any()) { //起点 //foreach (var startLocation in startLocations) //{ // //解锁被锁定的货位 CreateDAL().UpdateState(endLocation, "正常", "空", "预出库锁定", null); // BLLCreator.Create>().Update(new { CN_S_LOCATION_STATE = "正常", CN_S_USE_STATE = "满" }, new { CN_S_LOCATION_CODE = startLocation }); //} foreach (var endLocation in endLocations) { //解锁被锁定的货位 CreateDAL().UpdateState(endLocation, "正常", "空", "预出库锁定", null); BLLCreator.Create>().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>().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().ExecuteState(t.taskNo, "取消", logPara); }); } BLLCreator.Create>().Update(new { CN_S_STATE = "执行失败", CN_S_RESULT = callMaterialJobDto.BasisResponse.Message }, new { callMaterialJobDto.CallMaterialMst.CN_GUID }); } } }