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