using NX_CommonClassLibrary;
using NX_JsonClassLibrary;
using NX_ModelClassLibrary.BaseModel;
using NX_ModelClassLibrary.Common;
using NX_ModelClassLibrary.CrnModel;
using NX_ModelClassLibrary.CustomEnum;
using NX_ModelClassLibrary.OpcModel;
using NX_ModelClassLibrary.TranModel;
using NX_ModelClassLibrary.WcsDispatch;
using NX_ModelClassLibrary.WmsTask;
using NX_WcsBiz.CommonBusiness;
using NX_WcsDal.WcsDispatch;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NX_WcsBiz.WcsDispatch
{
///
/// 任务反馈调度类
///
public class TaskResponse_Disp
{
#region 单例模式
///
/// 单例模式对象
///
private static TaskResponse_Disp _instance = null;
private static readonly object lockObj = new object();
///
/// 单例模式方法
///
public static TaskResponse_Disp Instance
{
get
{
if (_instance == null)
{
lock (lockObj)
{
if (_instance == null)
{
_instance = new TaskResponse_Disp();
}
}
}
return _instance;
}
}
#endregion
///
/// 任务反馈调度入口函数
///
/// 任务反馈传入参数对象
///
public DispUntilityReturnMd TaskResponseHandleFunc(TaskResponseMd taskResponseMd)
{
try
{
if (taskResponseMd == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"任务反馈调度函数传入参数为空!!" };
}
DispUntilityReturnMd retMd;
switch (taskResponseMd.TaskResponseType)
{
case DispatchResponseHandleTypeEnum.输送线指令反馈完成:
retMd = TranTaskResponseHandle(taskResponseMd);
break;
case DispatchResponseHandleTypeEnum.堆垛机指令反馈完成:
retMd = CrnTaskResponseHandle(taskResponseMd);
break;
default:
retMd = new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"未定义任务反馈处理枚举,任务反馈调度无法识别此类型!!" };
break;
}
return retMd;
}
catch (Exception ex)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"任务反馈调度函数发生异常:【{ex.Message}】。" };
}
}
private DispUntilityReturnMd TranTaskResponseHandle(TaskResponseMd taskResponseMd)
{
BasWcsLocMd taskResponseLoc = BasCommon_Biz.Instance.allWcsLocList.FirstOrDefault(x => x.LocCode == taskResponseMd.CurrentLocNo);
if (taskResponseLoc == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"输送线任务反馈完成请求参数验证错误,传入站台不是系统配置好的站台号!{GetRetMsg(taskResponseMd)}" };
}
WcsTranCmdMd wcsTranCmdMd = TaskResponse_Dal.Instance.GetFinishedWcsTranCmdOfPalletCode(taskResponseMd.TrayCode, taskResponseMd.PalletCode, taskResponseMd.CurrentLocNo);
if (wcsTranCmdMd == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"输送线任务反馈完成请求参数验证错误,传入参数无法获取完成的输送线信息!{GetRetMsg(taskResponseMd)}" };
}
WmsTskTaskMd wmsTskTaskMd = TaskResponse_Dal.Instance.GetUnfinishWmsTaskOfTaskNo(taskResponseMd.TaskNo.ToString());
if (wmsTskTaskMd == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"输送线任务反馈完成请求参数验证错误,无法获取到未完成的WMS大任务数据!{GetRetMsg(taskResponseMd)}" };
}
if (taskResponseLoc.LocTypeCode == "InLoc")
{
string trayCode = string.Empty;
if (!TaskRequest_Dal.Instance.VerifyTrayMsgAndBalanceMsg(taskResponseMd.PalletCode, out trayCode))
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"输送线任务反馈完成请求参数验证错误,校验传入托盘号库存和组盘信息错误,无法进行下一步动作!{GetRetMsg(taskResponseMd)}" };
}
// ToDo:20201215 孙亚龙
BasWcsLocMd regionLocNo = BasCommon_Biz.Instance.allWcsLocList.FirstOrDefault(x => x.LocCode == wmsTskTaskMd.ElocCode);
BasBinMd CurrInBinMd = TaskResponse_Dal.Instance.GetBinMdOfCode(taskResponseLoc.LocBinExtMsg);
List DistributableShelfLst = BasCommon_Biz.Instance.GetCrnRelationShelfLst(CurrInBinMd);
// 获取空闲库位
BasBinMd emptyBin = BasCommon_Biz.Instance.GetDoubleExtensionEmptyBinMd(regionLocNo.LocBinExtMsg, DistributableShelfLst, trayCode);
if (emptyBin == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"获取库区:【{regionLocNo.LocExtMsg}】的空闲库位失败,输送线任务反馈无法进行下一步动作!{GetRetMsg(taskResponseMd)}" };
}
//生成堆垛机指令。更新WMS大任务当前站台为入库口站点。
BasBinMd inBinMd = TaskResponse_Dal.Instance.GetBinMdOfCodeAndType(taskResponseLoc.LocBinExtMsg, BasBinTypeEnum.入库口);
BasNextLocRouteMd locRouteMd = TaskResponse_Dal.Instance.GetRouteMsg(taskResponseLoc, regionLocNo);
if (locRouteMd == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"任务反馈的请求参数验证错误,获取起点:【{taskResponseLoc.LocCode}】到终点:【{regionLocNo.LocCode}】的路线信息发生错误!{GetRetMsg(taskResponseMd)}" };
}
int row = TaskResponse_Dal.Instance.InsertCrnCmdAndUpdateWmsTask(wmsTskTaskMd, emptyBin, inBinMd, locRouteMd);
if (row > 0)
{
OperateResultInfo resultInfo = JsonHelper.ToObject(HttpRequestHelper.POST(AppConfigHelper.Get("WebApiUrl"), JsonHelper.ToJsonExt(new NoticeWmsPalletStatus
{
TaskNo = wmsTskTaskMd.TaskNo,
TrayCode = wmsTskTaskMd.TrayCode,
OperateUserId = 3,// 暂时写死,后续增加WCS管理员账户
PalletCurrRunStatus = PalletTaskRunStatusEnum.托盘入库执行中,
})));
if (resultInfo.Status == OperateStatus.Success)
{
return new DispUntilityReturnMd { IsSuccess = true, RetMsg = $"输送线任务完成反馈处理成功!--{resultInfo.Message}" };
}
else
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"输送线任务完成反馈处理失败!调用WMS接口发生错误。 --{resultInfo.Message}" };
}
}
else
{
return new DispUntilityReturnMd { IsSuccess = true, RetMsg = "输送线任务完成反馈处理失败!生成下一步堆垛机指令错误!修改WMS大任务数据错误!!" };
}
}
else if (taskResponseLoc.LocTypeCode == "GeneralLoc" || taskResponseLoc.LocTypeCode == "OnLineLoc")
{
// ToDo:20201215 孙亚龙
//大任务到达出库分拣口。
int row = TaskResponse_Dal.Instance.UpdateWmsTaskToTargetLoc(wmsTskTaskMd);
if (row > 0)
{
OperateResultInfo resultInfo = JsonHelper.ToObject(HttpRequestHelper.POST(AppConfigHelper.Get("WebApiUrl"), JsonHelper.ToJsonExt(new NoticeWmsPalletStatus
{
TaskNo = wmsTskTaskMd.TaskNo,
TrayCode = wmsTskTaskMd.TrayCode,
OperateUserId = 3,// 暂时写死,后续增加WCS管理员账户
PalletCurrRunStatus = PalletTaskRunStatusEnum.托盘出库到目标,
})));
if (resultInfo.Status == OperateStatus.Success)
{
return new DispUntilityReturnMd { IsSuccess = true, RetMsg = $"输送线任务完成反馈处理成功!--{resultInfo.Message}" };
}
else
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"输送线任务完成反馈处理失败!调用WMS接口发生错误。 --{resultInfo.Message}" };
}
}
else
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = "输送线任务完成反馈处理失败!修改WMS大任务状态为托盘到目标错误!!" };
}
}
else
{
// ToDo:20201215 孙亚龙
// 由于目前的项目没有那么多站台类型,因此其它站台类型的代码暂时不添加。
// 后续项目使用到的话,再根据业务类型添加代码。
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"输送线任务反馈暂时未收录该类型站台的反馈业务,请联系管理员或程序设计者!{GetRetMsg(taskResponseMd)}" };
}
}
private BasWcsLocMd GetOutLocMd()
{
List locMdLst = BasCommon_Biz.Instance.allWcsLocList.FindAll(x => x.LocTypeCode == "OnLineAndGeneralLoc" || x.LocTypeCode == "GeneralLoc");
Dictionary tranLocHaveGoodsDic = new Dictionary();
for (int i = 0; i < locMdLst.Count; i++)
{
BasWcsDevMd basWcsTranDevMd = BasCommon_Biz.Instance.basWcsDevMdList.FirstOrDefault(x => x.DevCode == locMdLst[i].LocExtMsg);
if (GetTranHaveGoodsStatus(basWcsTranDevMd))
{
tranLocHaveGoodsDic.Add(locMdLst[i], true);
}
else
{
tranLocHaveGoodsDic.Add(locMdLst[i], false);
}
}
List tmpLocFalseLst = tranLocHaveGoodsDic.Where(x => x.Value == false).Select(x => x.Key).ToList();
if (tmpLocFalseLst.Count == 1)
{
return tmpLocFalseLst[0];
}
else if (tmpLocFalseLst.Count < 1)
{
Random tmpRd = new Random();
int retIndex = tmpRd.Next(0, locMdLst.Count);
return locMdLst[retIndex];
}
else
{
Random tmpRd = new Random();
int retIndex = tmpRd.Next(0, tmpLocFalseLst.Count);
return tmpLocFalseLst[retIndex];
}
}
private bool GetTranHaveGoodsStatus(BasWcsDevMd basWcsTranDevMd)
{
WcsOpcItemMd tmpFrontHaveGoodsFlagOpcItem = BasCommon_Biz.Instance.allOpcItemList.FirstOrDefault(x => x.DevCode == basWcsTranDevMd.DevCode && x.PlcCode == basWcsTranDevMd.DevPlcNo && x.OpcItemCode == "FrontHaveGoodsFlag");
WcsOpcItemMd tmpBackEndHaveGoodsFlagOpcItem = BasCommon_Biz.Instance.allOpcItemList.FirstOrDefault(x => x.DevCode == basWcsTranDevMd.DevCode && x.PlcCode == basWcsTranDevMd.DevPlcNo && x.OpcItemCode == "BackEndHaveGoodsFlag");
return Convert.ToBoolean(tmpFrontHaveGoodsFlagOpcItem.OpcItemValue) || Convert.ToBoolean(tmpBackEndHaveGoodsFlagOpcItem.OpcItemValue);
}
private DispUntilityReturnMd CrnTaskResponseHandle(TaskResponseMd taskResponseMd)
{
BasWcsLocMd taskResponseLoc = BasCommon_Biz.Instance.allWcsLocList.FirstOrDefault(x => x.LocCode == taskResponseMd.CurrentLocNo);
if (taskResponseLoc == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"堆垛机任务反馈完成请求参数验证错误,传入站台不是系统配置好的站台号!{GetRetMsg(taskResponseMd)}" };
}
WcsCrnCmdMd wcsCrnCmdMd = TaskResponse_Dal.Instance.GetFinishedWcsCrnCmdOfPalletCode(taskResponseMd.PalletCode,taskResponseMd.TrayCode);
if (wcsCrnCmdMd == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"堆垛机任务反馈完成请求参数验证错误,传入参数无法获取完成的堆垛机指令信息!{GetRetMsg(taskResponseMd)}" };
}
WmsTskTaskMd wmsTskTaskMd = TaskResponse_Dal.Instance.GetUnfinishWmsTaskOfTaskNo(taskResponseMd.TaskNo.ToString());
if (wmsTskTaskMd == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"堆垛机任务反馈完成请求参数验证错误,无法获取到未完成的WMS大任务数据!{GetRetMsg(taskResponseMd)}" };
}
//string trayCode = string.Empty;
//if (!TaskRequest_Dal.Instance.VerifyTrayMsgAndBalanceMsg(taskResponseMd.PalletCode, out trayCode))
//{
// return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"堆垛机任务反馈完成请求参数验证错误,校验传入托盘号库存和组盘信息错误,无法进行下一步动作!{GetRetMsg(taskResponseMd)}" };
//}
BasBinMd eBinMd = TaskResponse_Dal.Instance.GetBinMdOfCode(wmsTskTaskMd.EbinCode);
if (eBinMd.BinType == BasBinTypeEnum.存储库位 && taskResponseLoc.LocTypeCode == "RegionLoc" && wcsCrnCmdMd.CmdType == CrnCmdTypeEnum.IN)// 入库
{
// ToDo:20201215 孙亚龙
int row = TaskResponse_Dal.Instance.UpdateWmsTaskToTargetLoc(wmsTskTaskMd);
if (row > 0)
{
// ToDo:后续调用WMS接口,完成入库任务。
OperateResultInfo resultInfo = JsonHelper.ToObject(HttpRequestHelper.POST(AppConfigHelper.Get("WebApiUrl"), JsonHelper.ToJsonExt(new NoticeWmsPalletStatus
{
TaskNo = wmsTskTaskMd.TaskNo,
TrayCode = wmsTskTaskMd.TrayCode,
OperateUserId = 3,// 暂时写死,后续增加WCS管理员账户
PalletCurrRunStatus = PalletTaskRunStatusEnum.托盘入库完成,
})));
if (resultInfo.Status == OperateStatus.Success)
{
return new DispUntilityReturnMd { IsSuccess = true, RetMsg = $"堆垛机任务完成反馈处理成功!--{resultInfo.Message}" };
}
else
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"堆垛机任务完成反馈处理失败!调用WMS接口发生错误。 --{resultInfo.Message}" };
}
}
else
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = "堆垛机任务完成反馈处理失败!修改WMS大任务状态为托盘到目标错误!!" };
}
}
else if (eBinMd.BinType == BasBinTypeEnum.出库口 && taskResponseLoc.LocTypeCode == "OutLoc" && wcsCrnCmdMd.CmdType == CrnCmdTypeEnum.OUT)// 出库
{
//ToDo: 后续在这里增加判断1001和1008站台空闲的逻辑。增加动态均衡分配到两个作业口。
BasWcsLocMd eLocNo = GetOutLocMd();
//BasWcsLocMd eLocNo = BasCommon_Biz.Instance.allWcsLocList.FirstOrDefault(x => x.LocCode == wmsTskTaskMd.ElocCode);
if (eLocNo.LocCode != wmsTskTaskMd.ElocCode)
{
//更新WMS大任务终点位置。
wmsTskTaskMd.ElocCode = eLocNo.LocCode;
TaskResponse_Dal.Instance.UpdateWmsTaskElocNo(wmsTskTaskMd);
}
BasNextLocRouteMd locRouteMd = TaskResponse_Dal.Instance.GetRouteMsg(taskResponseLoc, eLocNo);
if (locRouteMd == null)
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"任务反馈的请求参数验证错误,获取起点:【{taskResponseLoc.LocCode}】到终点:【{eLocNo.LocCode}】的路线信息发生错误!{GetRetMsg(taskResponseMd)}" };
}
int row = TaskResponse_Dal.Instance.InsertTranCmdAndUpdateWmsTask(wmsTskTaskMd, taskResponseLoc, eLocNo, locRouteMd);
if (row > 0)
{
OperateResultInfo resultInfo = JsonHelper.ToObject(HttpRequestHelper.POST(AppConfigHelper.Get("WebApiUrl"), JsonHelper.ToJsonExt(new NoticeWmsPalletStatus
{
TaskNo = wmsTskTaskMd.TaskNo,
TrayCode = wmsTskTaskMd.TrayCode,
OperateUserId = 3,// 暂时写死,后续增加WCS管理员账户
PalletCurrRunStatus = PalletTaskRunStatusEnum.托盘出库执行中,
})));
if (resultInfo.Status == OperateStatus.Success)
{
return new DispUntilityReturnMd { IsSuccess = true, RetMsg = $"堆垛机任务完成反馈处理成功!--{resultInfo.Message}" };
}
else
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"堆垛机任务完成反馈处理失败!调用WMS接口发生错误。 --{resultInfo.Message}" };
}
}
else
{
return new DispUntilityReturnMd { IsSuccess = true, RetMsg = "堆垛机任务完成反馈处理失败!生成下一步输送线指令错误!修改WMS大任务数据错误!!" };
}
}
else if (eBinMd.BinType == BasBinTypeEnum.存储库位 && taskResponseLoc.LocTypeCode == "RegionLoc" && wcsCrnCmdMd.CmdType == CrnCmdTypeEnum.MOVE)
{
TaskResponse_Dal.Instance.UpdateMoveWmsTaskAndBalance(wmsTskTaskMd);
return new DispUntilityReturnMd { IsSuccess = true, RetMsg = $"堆垛机移库指令完成,任务反馈处理成功!" };
}
else
{
return new DispUntilityReturnMd { IsSuccess = false, RetMsg = $"堆垛机任务反馈终点库位类型为入库口,不符合实际情况,请联系管理员或程序设计者,检查堆垛机指令是否生成有误!{GetRetMsg(taskResponseMd)}" };
}
}
private string GetRetMsg(TaskResponseMd taskResponseMd)
{
return $"反馈传入参数 --- 托盘号:【{taskResponseMd.PalletCode}】,请求站台号:【{taskResponseMd.CurrentLocNo}】,反馈处理类型:【{taskResponseMd.TaskResponseType}】";
}
}
}