using HH.WCS.Mobox3.FJJF.models;
|
using HH.WCS.Mobox3.FJJT.device;
|
using HH.WCS.Mobox3.FJJT.dispatch;
|
using HH.WCS.Mobox3.FJJT.models;
|
using HH.WCS.Mobox3.FJJT.process;
|
using HH.WCS.Mobox3.FJJT.util;
|
using HH.WCS.Mobox3.FJJT.wms;
|
using Newtonsoft.Json;
|
using NLog;
|
using NLog.Fluent;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.Linq;
|
using System.Reflection;
|
using System.Reflection.Emit;
|
using System.Threading;
|
using static HH.WCS.Mobox3.FJJT.api.ApiModel;
|
using static HH.WCS.Mobox3.FJJT.api.OtherModel;
|
using static HH.WCS.Mobox3.FJJT.api.WmsController;
|
using static HH.WCS.Mobox3.FJJT.util.ExcetionHelper;
|
using static HH.WCS.Mobox3.FJJT.util.Settings;
|
using static System.Net.Mime.MediaTypeNames;
|
|
namespace HH.WCS.Mobox3.FJJT.api {
|
/// <summary>
|
/// api接口辅助类
|
/// </summary>
|
public class ApiHelper {
|
static ApiHelper() {
|
|
}
|
|
/// <summary>
|
/// 空工装出库
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult emptyPalletOutStock(OutStockModel model) {
|
ResponseResult result = new ResponseResult();
|
|
Location endLoc = LocationHelper.GetLoc(model.endLocCode);
|
if (endLoc == null)
|
{
|
WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库,WMS系统未查询到终点货位:{model.endLocCode}");
|
throw new BusinessException($"空工装出库,WMS系统未查询到终点货位:{model.endLocCode},请检查终点货位编码是否正确");
|
}
|
else if (endLoc.N_LOCK_STATE != 0)
|
{
|
WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库,终点货位:{model.endLocCode}处于锁定状态");
|
throw new BusinessException($"空工装出库,终点货位:{model.endLocCode}处于锁定状态");
|
}
|
|
var areaCodes = Settings.getRelAreaCodes(endLoc.S_AREA_CODE);
|
if (areaCodes.Count == 0)
|
{
|
WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库,未配置库区:{endLoc.S_AREA_CODE}的关联关系");
|
throw new BusinessException($"空工装出库,未配置库区:{endLoc.S_AREA_CODE}的关联关系");
|
}
|
|
Location startLoc = WMSHelper.getOutStockStartLoc(areaCodes[0], null);
|
if (startLoc == null)
|
{
|
WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库,库区:{areaCodes[0]}未查询到空工装");
|
throw new BusinessException($"空工装出库,未查询到空工装,立库可能缺少空工装");
|
}
|
|
var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE);
|
if (locCntrRels.Count > 0)
|
{
|
string cntrCode = locCntrRels[0].S_CNTR_CODE;
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = cntrCode,
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_TYPE = "空工装出库任务",
|
S_OP_DEF_NAME = "空工装出库",
|
N_PRIORITY = 10,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
// 创建一段入库任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE,
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = wmsTask.N_PRIORITY,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
}
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "中", $"查询的空工装有误,错误原因:未查询到货位容器的绑定关系");
|
throw new BusinessException($"查询空工装错误,未查询到货位容器的绑定关系,请联系开发人员排查");
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// WCS读码请求流程
|
/// 业务场景:读码入库、读码出库
|
/// 1.判断RFID是否存在WMS系统中,否,则默认为RFID无法识别
|
/// 2.判断RFID是否与任务RFID是否一致
|
/// 3.记录RFID异常信息
|
/// </summary>
|
/// <param name="request"></param>
|
/// <returns></returns>
|
public static ResponseResult readCodeProcess(ReadCodeRequest request) {
|
ResponseResult responseResult = new ResponseResult();
|
|
Location loc = LocationHelper.GetLoc(request.loc);
|
if (loc != null)
|
{
|
var cst = WCSHelper.GetTask(request.taskNo);
|
if (cst != null)
|
{
|
var container = ContainerHelper.GetCntr(request.cntrNo);
|
if (container != null)
|
{
|
if (cst.S_CNTR_CODE != request.cntrNo)
|
{
|
ContainerHelper.UpdateCntrState(cst.S_CNTR_CODE, 1);
|
WMSHelper.addRfidAnomalyRecord(cst.S_CNTR_CODE, 2, request.loc, cst.S_CODE);
|
}
|
}
|
else
|
{
|
ContainerHelper.UpdateCntrState(cst.S_CNTR_CODE, 1);
|
WMSHelper.addRfidAnomalyRecord(cst.S_CNTR_CODE, 1, request.loc, cst.S_CODE);
|
}
|
|
/*WCSHelper.ActivatePreCreateTask(cst.S_OP_CODE);*/
|
|
// 方案2 4.如果读取不成功,查看异常区是否有空货位
|
/* var agvEndLoc = WMSHelper.GetTransfeRelevanceLoc(loc.S_AREA_CODE, "4");
|
if (agvEndLoc != null)
|
{
|
// 4.1 有,则创建搬运异常区任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = cst.S_OP_NAME,
|
S_OP_CODE = cst.S_OP_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = cst.S_CNTR_CODE,
|
S_TYPE = "异常工装移库异常区",
|
S_START_LOC = loc.S_CODE,
|
S_START_AREA = loc.S_AREA_CODE,
|
S_END_LOC = agvEndLoc.S_CODE,
|
S_END_AREA = agvEndLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "AGV",
|
N_PRIORITY = 99,
|
T_START_TIME = DateTime.Now,
|
};
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、接驳点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 1);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
|
WCSHelper.CancelPreCreateTask(cst.S_OP_CODE);
|
}
|
}
|
else
|
{
|
// 4.2 无,则记录异常激活预创建任务
|
WCSHelper.ActivatePreCreateTask(cst.S_OP_CODE);
|
}*/
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "低", $"没有查询到读码的任务,任务号:{request.taskNo}");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "中", $"读码位:{request.loc},没有在WMS系统中录入");
|
throw new BusinessException($"读码位:{request.loc},没有在WMS系统中录入");
|
}
|
return responseResult;
|
}
|
|
|
/// <summary>
|
/// 满料下线流程
|
/// 1.判断RFID是否读取成功,读取不成功,记录异常(读取失败后,临时生成一个托盘码)
|
/// 2.根据RFID查询中间表,不存在,记录异常
|
/// 3.判断满料接驳位对应的空工装缓存位状态(查询线体光电)
|
///
|
/// 直连
|
/// 4.需要补,则生成空工装出库任务(胎面、胎侧直连提高优先级)
|
/// 5.下发满料搬运任务(帘布直连提高优先级)
|
///
|
/// 非直连
|
/// 4.需要补空工装,则空工装出库任务(完成后,生成满料搬运任务,并提高优先级99)
|
/// 5.不需要补空工装,则生成满料搬运任务
|
///
|
/// 6.读任务中间表
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult offLineProcess(OffLineRequest model) {
|
ResponseResult responseResult = new ResponseResult();
|
|
var areaCodes = Settings.areaPropertyList.Select(a => a.areaCode).ToList();
|
var isExistCntr = LocationHelper.checkAreaExistCntr(areaCodes,model.cntrNo);
|
if (!isExistCntr)
|
{
|
// 查询起点货位是否存在已存在任务,防止任务重复发起
|
var existWmsTask = WMSHelper.GetWmsTaskByStart(model.loc);
|
if (existWmsTask == null)
|
{
|
// 查询对应机台的物料下线配置信息
|
var logicConfig = WMSHelper.getLogicConfigByJtCode(model.jtNo);
|
if (logicConfig != null)
|
{
|
Container container = ContainerHelper.GetCntr(model.cntrNo);
|
if (container == null || !model.isNormal)
|
{
|
ContainerHelper.AddCntr(model.cntrNo);
|
ContainerHelper.UpdateCntrState(model.cntrNo, 1);
|
WMSHelper.addRfidAnomalyRecord(model.cntrNo, 1, model.loc, null);
|
}
|
|
// 根据物料下线配置信息,判断任务类型是直连下线还是非直连下线
|
if (logicConfig.S_TASK_TYPE == "1" || logicConfig.S_TASK_TYPE == "2")
|
{
|
triggerItemOffLineFlow(model.loc, model.cntrNo, logicConfig);
|
}
|
else
|
{
|
// 满料下线(非直连)
|
triggerItemOffLineFlow4(model.loc, model.cntrNo, logicConfig);
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"机台号{model.jtNo},没有可用的逻辑线路,请联系管理人员");
|
throw new BusinessException($"机台号{model.jtNo},没有可用的逻辑线路,请联系管理人员");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "低", $"下线货位:{model.loc}已有任务,请勿重复下发任务");
|
throw new BusinessException($"下线货位:{model.loc}已有任务,请勿重复下发任务");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"工装:{model.cntrNo}已入库,请勿重复入库");
|
throw new BusinessException($"工装:{model.cntrNo}已入库,请勿重复入库");
|
}
|
return responseResult;
|
}
|
|
|
/// <summary>
|
/// 满料下线(非直连)
|
/// 1.创建满料下线作业
|
/// 2.判断是否需要补空工装,需要则创建空工装补缓存位任务
|
/// 3.判断容器是否是异常工装,是,如异常区有空货位则创建异常工装入线边异常区任务;否,则创建满料工装入库任务(如需要补空工装,则将任务状态改为预创建,等待补空工装任务完成后触发)
|
/// 4.作业创建完成后,读取中间表,更新中间表状态
|
/// </summary>
|
/// <param name="offLineLoc"></param>
|
/// <param name="logicConfig"></param>
|
/// <param name="cntrNo"></param>
|
/// <returns></returns>
|
public static bool triggerItemOffLineFlow4(string offLineLoc,string cntrNo, LogicConfig logicConfig ,LjMesTask mesTask = null)
|
{
|
bool result = true;
|
try
|
{
|
if (mesTask == null)
|
{
|
mesTask = WMSHelper.getLjMesTaskByCntr(cntrNo);
|
}
|
|
if (mesTask != null)
|
{
|
// 2.判断是否需要补空工装,需要,则创建空工装出库任务
|
bool photoStatus = false;
|
var hcLoc = LocationHelper.GetLoc(logicConfig.S_LKBKHCLOC);
|
if (hcLoc != null)
|
{
|
if (hcLoc.N_CURRENT_NUM != 0 && hcLoc.N_LOCK_STATE == 0)
|
{
|
hcLoc = LocationHelper.GetEmptyLoc(hcLoc.S_AREA_CODE);
|
}
|
|
if (hcLoc != null)
|
{
|
var bufferLocConfig = Settings.GetBufferLocConfig(hcLoc.S_CODE); // 缓存位关联属性
|
if (bufferLocConfig != null || hcLoc.N_CURRENT_NUM == 0)
|
{
|
photoStatus = true;
|
// 方案1,如果非直连的缓存位有光电信号,则查询设备状态判断是否需要补空工装
|
/* var deviceStatusDatas = WCSDispatch.getDeviceStatus(new List<string>() { bufferLocConfig.deviceNo });
|
if (deviceStatusDatas != null && deviceStatusDatas.Count > 0)
|
{
|
var deviceStatus = deviceStatusDatas[0];
|
if (deviceStatus.workStatus == 1 && deviceStatus.manualStatus == 0)
|
{
|
photoStatus = deviceStatus.photoStatus == 1;
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"设备号:{bufferLocConfig.deviceNo},设备当前处于不可用状态,请联系管理人员调整设备状态");
|
throw new BusinessException($"设备号:{bufferLocConfig.deviceNo},设备当前处于不可用状态,请联系管理人员调整设备状态");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"设备号:{bufferLocConfig.deviceNo},查询设备状态失败,请联系工作人员查看设备是否正常");
|
throw new BusinessException($"设备号:{bufferLocConfig.deviceNo},查询设备状态失败,请联系工作人员查看设备是否正常");
|
}*/
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"缓存位:{logicConfig.S_LKBKHCLOC},没有配置属性信息,请联系管理人员配置");
|
throw new BusinessException($"缓存位:{logicConfig.S_LKBKHCLOC},没有配置属性信息,请联系管理人员配置");
|
}
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"缓存位:{logicConfig.S_LKBKHCLOC},没有WMS系统中录入");
|
throw new BusinessException($"缓存位:{logicConfig.S_LKBKHCLOC},没有WMS系统中录入");
|
}
|
|
// 空工装出库判断条件
|
Location kgzStartLoc = null;
|
Location kgzEndLoc = null;
|
string kgzCntrCode = null;
|
if (photoStatus)
|
{
|
kgzStartLoc = LocationHelper.GetLoc(logicConfig.S_LKKTJBLOC);
|
kgzEndLoc = LocationHelper.GetLoc(logicConfig.S_LKBKHCLOC);
|
if (kgzStartLoc == null)
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"库区:{logicConfig.S_AREA_CODE},没有可用的空工装");
|
photoStatus = false;
|
}
|
if (kgzEndLoc == null)
|
{
|
WMSHelper.addAlarmRecord("流程异常", "中", $"空工装缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入");
|
photoStatus = false;
|
}
|
|
var locCntrRels = LocationHelper.GetLocCntr(kgzStartLoc.S_CODE);
|
if (locCntrRels.Count > 0)
|
{
|
kgzCntrCode = locCntrRels[0].S_CNTR_CODE;
|
}
|
else
|
{
|
kgzCntrCode = "虚拟容器";
|
WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库站台:{logicConfig.S_LKKTJBLOC},没有空工装");
|
}
|
}
|
|
string cntrCode = mesTask.PALLET_ID;
|
Location startLoc = LocationHelper.GetLoc(offLineLoc);
|
if (startLoc != null)
|
{
|
// 1.创建满料下线作业
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = cntrCode,
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = "虚拟货位",
|
S_END_AREA = "虚拟库区",
|
S_TYPE = "满料/异常工装入库任务(非直连)",
|
S_OP_DEF_NAME = "满料/异常工装入库任务(非直连)",
|
S_OP_DEF_CODE = mesTask.ID.ToString(),
|
T_START_TIME = DateTime.Now,
|
};
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
int priority = 10;
|
// 2.判断是否需要补空工装,需要则创建空工装补缓存位任务
|
if (photoStatus)
|
{
|
WCSTask kgzWcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = kgzCntrCode,
|
S_TYPE = "空工装出库任务",
|
S_START_LOC = kgzStartLoc.S_CODE,
|
S_START_AREA = kgzStartLoc.S_AREA_CODE,
|
S_END_LOC = kgzEndLoc.S_CODE,
|
S_END_AREA = kgzEndLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "AGV",
|
N_PRIORITY = priority,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(kgzWcsTask))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(kgzWcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(kgzWcsTask.S_END_LOC, 1);
|
}
|
}
|
|
// 3.创建满料工装入库任务(如需要补空工装,则将任务状态改为预创建,等待补空工装任务完成后触发)
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_TYPE = "满料工装入库任务(非直连)",
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = wmsTask.S_END_LOC,
|
S_END_AREA = wmsTask.S_END_AREA,
|
S_SCHEDULE_TYPE = "AGV",
|
N_PRIORITY = 99,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (photoStatus)
|
{
|
wcsTask.N_B_STATE = -1;
|
wcsTask.S_B_STATE = "预创建";
|
}
|
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
|
// 4.作业创建完成后,读取中间表,更新中间表状态
|
WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE, mesTask.ID);
|
}
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "中", $"下线位:{offLineLoc},没有在WMS系统中录入");
|
throw new BusinessException($"下线位:{offLineLoc},没有在WMS系统中录入");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "中", $"非直连下线货位:{offLineLoc}触发下线请求,未查询到MES任务");
|
throw new BusinessException($"非直连下线货位:{offLineLoc}触发下线请求,未查询到MES任务");
|
}
|
}
|
catch (BusinessException be)
|
{
|
throw be;
|
}
|
catch (Exception ex)
|
{
|
WMSHelper.addAlarmRecord("系统错误", "高", ex.Message);
|
LogHelper.Error("WMS内部错误:触发满料下线(非直连)作业错误 ; ERROR_MGS:" + ex.Message, ex, "WMS");
|
result = false;
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// 满料下线(直连)
|
/// 1.创建满料下线作业
|
/// 2.判断是否需要补空工装,需要,则创建空工装出库任务
|
/// 3.创建满料入库任务
|
/// 4.判断直连模式,如是胎侧直连模式,则提高空工装出库任务优先级;如是帘布直连模式则,提高满料入库优先级
|
/// 5.作业创建完成后,读取中间表,更新中间表状态
|
/// </summary>
|
/// <param name="offLineLoc">下线货位</param>
|
/// <param name="cntrNo">下线容器编码</param>
|
/// <param name="logicConfig">逻辑配置</param>
|
/// <returns></returns>
|
public static bool triggerItemOffLineFlow(string offLineLoc, string cntrNo, LogicConfig logicConfig ) {
|
bool result = true;
|
try
|
{
|
// 2.判断是否需要补空工装,需要,则创建空工装出库任务
|
bool photoStatus = false;
|
var hcLoc = LocationHelper.GetLoc(logicConfig.S_LKBKHCLOC);
|
if (hcLoc != null)
|
{
|
var bufferLocConfig = Settings.GetBufferLocConfig(hcLoc.S_CODE);
|
if (bufferLocConfig != null)
|
{
|
// 测试代码
|
photoStatus = true;
|
|
/* // 业务代码,勿删
|
var deviceStatusDatas = WCSDispatch.getDeviceStatus(new List<string>() { bufferLocConfig.deviceNo });
|
if (deviceStatusDatas != null && deviceStatusDatas.Count > 0)
|
{
|
var deviceStatus = deviceStatusDatas[0];
|
if (deviceStatus.workStatus == 1 && deviceStatus.manualStatus == 0)
|
{
|
photoStatus = deviceStatus.photoStatus == 1;
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"设备号:{bufferLocConfig.deviceNo},设备当前处于不可用状态,请联系管理人员调整设备状态");
|
throw new BusinessException($"设备号:{bufferLocConfig.deviceNo},设备当前处于不可用状态,请联系管理人员调整设备状态");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"设备号:{bufferLocConfig.deviceNo},查询设备状态失败,请联系工作人员查看设备是否正常");
|
throw new BusinessException($"设备号:{bufferLocConfig.deviceNo},查询设备状态失败,请联系工作人员查看设备是否正常");
|
}*/
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"缓存位:{logicConfig.S_LKBKHCLOC},没有配置属性信息,请联系管理人员配置");
|
throw new BusinessException($"缓存位:{logicConfig.S_LKBKHCLOC},没有配置属性信息,请联系管理人员配置");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入");
|
throw new BusinessException($"缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入");
|
}
|
|
Location startLoc = LocationHelper.GetLoc(offLineLoc);
|
if (startLoc == null)
|
{
|
WMSHelper.addAlarmRecord("流程异常", "中", $"下线位:{offLineLoc},没有在WMS系统中录入");
|
throw new BusinessException($"下线位:{offLineLoc},没有在WMS系统中录入");
|
}
|
|
Location endLoc = WMSHelper.getInStockEndLoc(logicConfig.S_AREA_CODE, 1);
|
if (endLoc == null)
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"库内没有空余货位");
|
throw new BusinessException($"库内没有空余货位");
|
}
|
|
LjMesTask mesTask = WMSHelper.getLjMesTaskByCntr(cntrNo);
|
// 1.创建满料下线作业
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = cntrNo,
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_TYPE = "满料/异常工装入库任务(直连)",
|
S_OP_DEF_NAME = "满料/异常工装入库任务(直连)",
|
S_OP_DEF_CODE = mesTask != null ? mesTask.ID.ToString() : null,
|
T_START_TIME = DateTime.Now,
|
};
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
int priority = 10;
|
Dictionary<int, WCSTask> taskDic = new Dictionary<int, WCSTask>();
|
|
// 是否创建空工装出口任务
|
if (photoStatus || true )
|
{
|
Location kgzStartLoc = WMSHelper.getOutStockStartLoc(logicConfig.S_AREA_CODE, null);
|
Location kgzEndLoc = LocationHelper.GetLoc(logicConfig.S_LKBKHCLOC);
|
if (kgzStartLoc == null)
|
{
|
WMSHelper.DeleteWmsTask(wmsTask.S_CODE);
|
WMSHelper.addAlarmRecord("流程异常", "高", $"库区:{logicConfig.S_AREA_CODE},没有可用的空工装");
|
throw new BusinessException($"库区:{logicConfig.S_AREA_CODE},没有可用的空工装");
|
}
|
if (kgzEndLoc == null)
|
{
|
WMSHelper.DeleteWmsTask(wmsTask.S_CODE);
|
WMSHelper.addAlarmRecord("流程异常", "中", $"空工装缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入");
|
throw new BusinessException($"空工装缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入");
|
}
|
|
var locCntrRels = LocationHelper.GetLocCntr(kgzStartLoc.S_CODE);
|
if (locCntrRels.Count > 0)
|
{
|
string kgzCntrCode = locCntrRels[0].S_CNTR_CODE;
|
// 如是胎侧直连模式,则提高空工装出库任务优先级
|
if (logicConfig.S_TASK_TYPE == "1")
|
{
|
priority = 99;
|
}
|
WCSTask kgzWcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = kgzCntrCode,
|
S_TYPE = "空工装出库任务",
|
S_START_LOC = kgzStartLoc.S_CODE,
|
S_START_AREA = kgzStartLoc.S_AREA_CODE,
|
S_END_LOC = kgzEndLoc.S_CODE,
|
S_END_AREA = kgzEndLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = priority,
|
T_START_TIME = DateTime.Now,
|
};
|
taskDic.Add(priority, kgzWcsTask);
|
}
|
else
|
{
|
WMSHelper.DeleteWmsTask(wmsTask.S_CODE);
|
WMSHelper.addAlarmRecord("流程异常", "高", $"查询空工装货位错误,货位:{kgzStartLoc.S_CODE}没有空工装");
|
throw new BusinessException($"查询空工装货位错误,货位:{kgzStartLoc.S_CODE}没有空工装");
|
}
|
}
|
|
// 如是帘布直连模式则,提高满料入库优先级
|
if (logicConfig.S_TASK_TYPE == "2")
|
{
|
priority = 99;
|
}
|
else
|
{
|
priority = 10;
|
}
|
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE,
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = priority,
|
T_START_TIME = DateTime.Now,
|
};
|
taskDic.Add(priority, wcsTask);
|
|
var tasks = taskDic.OrderByDescending(a => a.Key).Select(a => a.Value).ToList();
|
foreach (var task in tasks)
|
{
|
if (WCSHelper.CreateTask(task))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(task.S_START_LOC, 2);
|
LocationHelper.LockLoc(task.S_END_LOC, 1);
|
}
|
}
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
|
// 5.作业创建完成后,读取中间表,更新中间表状态
|
if (mesTask != null)
|
{
|
WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE, mesTask.ID);
|
}
|
else
|
{
|
ContainerHelper.UpdateCntrState(cntrNo, 1);
|
WMSHelper.addRfidAnomalyRecord(cntrNo, 3, offLineLoc, null);
|
}
|
}
|
}
|
catch (BusinessException be)
|
{
|
throw be;
|
}
|
catch (Exception ex)
|
{
|
// 报警:WMS内部错误:触发满料工装下线作业错误
|
WMSHelper.addAlarmRecord("系统错误", "高", ex.Message);
|
LogHelper.Info($"WMS内部错误:触发满料工装下线作业错误 ; 错误原因:{ex.Message}", "WMS");
|
result = false;
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// 叫料请求
|
/// 1.查询中间表,判断是否是环带物料
|
/// 2.查询库区物料信息,并过滤故障的堆垛机立库
|
/// 3.无库存写入中间表异常和异常原因
|
/// 4.计算出库货位,生成出库任务
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult callMaterialProcess(CallMaterialRequest model)
|
{
|
ResponseResult responseResult = new ResponseResult();
|
var mesTask = WMSHelper.getLjMesTaskByLoc(model.loc);
|
if (mesTask != null)
|
{
|
Location endLoc = LocationHelper.GetLoc(model.loc);
|
Location startLoc = null;
|
Location middleLoc = null;
|
string scheduleType = "";
|
if (mesTask.PALLET_TYPE == "环带")
|
{
|
scheduleType = "HDK";
|
// 查询环带库该物料库存情况,并比较与中转库的库存进行比较,先入先出
|
}
|
else
|
{
|
scheduleType = "WCS";
|
// 查询库区物料信息,根据先入先出原则计算,物料起点
|
startLoc = WMSHelper.getOutStockStartLoc(null, mesTask.MATERIAL_CODE);
|
}
|
|
if (startLoc == null)
|
{
|
// 无库存写入中间表异常和异常原因
|
mesTask.RETURN_CODE = "6";
|
mesTask.RECEIVE_MSG = "没有库存或设备故障无法出库";
|
WMSHelper.updateLjMesTask(mesTask);
|
|
WMSHelper.addAlarmRecord("流程异常", "低", $"MES叫料任务{mesTask.ID},没有库存或设备故障无法出库");
|
responseResult.code = 1;
|
responseResult.msg = "没有库存或设备故障无法出库";
|
return responseResult;
|
}
|
|
middleLoc = WMSHelper.GetMinTaskTransfeLoc(startLoc.S_AREA_CODE, 2 , 2);
|
if (middleLoc == null) {
|
WMSHelper.addAlarmRecord("流程异常", "高", $"MES叫料任务{mesTask.ID},立库接驳位可能处于锁定或禁用状态,请查看");
|
responseResult.code = 1;
|
responseResult.msg = "立库接驳位可能处于锁定或禁用状态";
|
return responseResult;
|
}
|
|
String cntrCode = "";
|
var locCntrs = LocationHelper.GetLocCntr(startLoc.S_CODE);
|
if (locCntrs != null && locCntrs.Count > 0)
|
{
|
cntrCode = locCntrs[0].S_CNTR_CODE;
|
}
|
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = "",
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_TYPE = "满料出库任务",
|
N_PRIORITY = 10,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
// 创建一段入库任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE,
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = middleLoc.S_CODE,
|
S_END_AREA = middleLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = scheduleType,
|
N_PRIORITY = wmsTask.N_PRIORITY,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
LocationHelper.LockLoc(wmsTask.S_END_LOC, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
WMSHelper.updateMesTaskStatus("", "2");
|
|
// 任务创建成功读取MES任务
|
WMSHelper.readLjMesCallItemTask("", mesTask.ID);
|
}
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"MES叫料任务{mesTask.ID},MES中间表没有该线边货位的叫料任务,请查看");
|
responseResult.code = 1;
|
responseResult.msg = "MES中间表没有该线边货位的叫料任务";
|
}
|
return responseResult;
|
}
|
|
|
/// <summary>
|
/// WCS任务状态回报
|
/// 任务状态 1:开始/执行中;完成;3:准备取货;4:取货完成;5:准备卸货;6:卸货完成;7:异常取消;8:强制完成
|
/// 1.根据任务状态回报更新货位状态、任务状态
|
/// 2.更新任务中间表状态
|
/// 4.更新出库任务中间表状态
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult taskStatusFeedback(TaskStatusFeedbackModel model)
|
{
|
ResponseResult responseResult = new ResponseResult();
|
WCSTask cst = WCSHelper.GetTask(model.taskNo);
|
if (cst != null)
|
{
|
WMSTask mst = WMSHelper.GetWmsTask(cst.S_OP_CODE);
|
if (mst != null)
|
{
|
switch (model.status)
|
{
|
case 1:
|
WCSHelper.Begin(cst);
|
WMSHelper.updateMesTaskStatus(mst.S_CODE, "2");
|
if (cst.S_TYPE.Contains("出库"))
|
{
|
WMSHelper.addLotOutTask(mst.S_START_LOC);
|
}
|
break;
|
case 2:
|
WCSHelper.End(cst);
|
break;
|
case 3:
|
WCSHelper.UpdateStatus(cst, "准备取货");
|
break;
|
case 4:
|
WCSHelper.UpdateStatus(cst, "取货完成");
|
TaskProcess.OperateStatus(cst, 4);
|
break;
|
case 5:
|
WCSHelper.UpdateStatus(cst, "准备卸货");
|
break;
|
case 6:
|
WCSHelper.UpdateStatus(cst, "卸货完成");
|
TaskProcess.OperateStatus(cst, 6);
|
break;
|
case 7:
|
WCSHelper.UpdateStatus(cst, "异常取消");
|
TaskProcess.OperateStatus(cst, 7);
|
mst.N_B_STATE = 3;
|
WMSHelper.UpdateTaskState(mst);
|
WMSHelper.updateMesTaskStatus(mst.S_CODE, "5", "WCS异常取消任务");
|
WMSHelper.addAlarmRecord("流程异常", "高", $"WCS异常取消任务,任务号:{cst.S_CODE}");
|
break;
|
case 8:
|
WCSHelper.UpdateStatus(cst, "强制完成");
|
break;
|
}
|
// 添加WCS动作记录
|
WCSHelper.AddActionRecord(model.taskNo, model.status, model.deviceNo, model.loc);
|
|
if (model.status == 2 || model.status == 8)
|
{
|
|
if (cst.S_TYPE.Contains("入库"))
|
{
|
var cntrItemRels = ContainerHelper.GetCntrItemRel(cst.S_CNTR_CODE);
|
if (cntrItemRels != null && cntrItemRels.Count > 0)
|
{
|
foreach (var cntrItem in cntrItemRels)
|
{
|
cntrItem.T_INBOUND_TIME = DateTime.Now;
|
ContainerHelper.updateCntrItemRel(cntrItem);
|
}
|
}
|
}
|
|
if (cst.S_TYPE.Contains("【异常】"))
|
{
|
WCSHelper.ActivatePreCreateTask(mst.S_CODE, 1);
|
}
|
else
|
{
|
WCSHelper.ActivatePreCreateTask(mst.S_CODE);
|
}
|
|
if (WMSHelper.isFinishTask(mst.S_CODE))
|
{
|
// 更新作业任务状态
|
mst.N_B_STATE = 2;
|
mst.T_END_TIME = DateTime.Now;
|
WMSHelper.UpdateTaskState(mst);
|
|
// 更新任务中间表状态
|
WMSHelper.updateMesTaskStatus(mst.S_CODE, "3");
|
|
if (cst.S_TYPE.Contains("出库"))
|
{
|
// 更新出库任务中间表状态
|
WMSHelper.updateLotOutTask(cst.S_CNTR_CODE, "2");
|
}
|
}
|
}
|
}
|
}
|
return responseResult;
|
}
|
|
/// <summary>
|
/// WCS申请终点
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult applyDest(ApplyDestinationModel model) {
|
ResponseResult result = new ResponseResult();
|
|
ApplyDest applyDest = new ApplyDest();
|
WCSTask cst = WCSHelper.GetTask(model.taskNo);
|
if (cst != null && cst.N_B_STATE < 3)
|
{
|
WMSTask mst = WMSHelper.GetWmsTask(cst.S_OP_CODE);
|
if (mst != null && mst.N_B_STATE < 2) {
|
|
int emptyFlag = 0; // 容器空满标识
|
var cntrItemRels = ContainerHelper.GetCntrItemRel(cst.S_CNTR_CODE);
|
if (cntrItemRels.Count > 0) {
|
emptyFlag = 1;
|
}
|
|
// 1:堆垛机放货异常申请新终点
|
if (model.applyType == 1) {
|
// 报警:流程异常
|
WMSHelper.addAlarmRecord("流程异常", "中", $"堆垛机放货异常,任务号:{cst.S_CODE},异常货位:{cst.S_END_LOC}");
|
|
// 1.将异常货位上锁,并报警
|
LocationHelper.LockLoc(cst.S_END_LOC, 3);
|
|
// 2.查询新的入库终点
|
Location endLoc = WMSHelper.getInStockEndLoc(cst.S_END_AREA, emptyFlag );
|
cst.S_END_LOC = endLoc.S_CODE;
|
WCSHelper.UpdateEndLoc(cst);
|
|
LocationHelper.LockLoc(endLoc.S_CODE, 1);
|
applyDest.destLoc = endLoc.S_CODE;
|
}
|
}
|
}
|
result.data = applyDest;
|
return result;
|
}
|
|
/// <summary>
|
/// AGV申请终点
|
/// 顺序 RFID验证 -> RFID与任务号验证 -> 物料合格状态验证 -> 虚拟终点
|
/// 申请类型: 1.虚拟终点 2.RFID与任务不匹配 3.物料状态不合格
|
/// 入库策略:先计算库区的容积率,再计算库区对应的入库站台的任务数,都取最小的
|
///
|
/// 1.确定任务是否在执行中
|
/// 2.判断申请类型
|
/// 1).虚拟终点,计算入库站台,同时预先生成入库站台-立库终点的搬运任务
|
/// 2).RFID验证失败,记录异常,并计算异常区的空货位
|
/// 3).RFID与任务不匹配,记录异常并报警,并计算异常区的空货位
|
/// 4).物料状态不合格,记录异常,计算入库站台,同时预先生成入库站台-立库终点的搬运任务 ;最后重新生成新的出库任务
|
///
|
/// 3. 2)\3) 异常区没有空货位,计算入库站台,同时预先生成入库站台-立库终点的搬运任务
|
///
|
/// 4.余料/空工装回库任务
|
/// 1).根据RFID查询中间表,判断物料类型,如为空工装,正常入库(计算入库站台,生成预创建搬运任务)
|
/// 2).如是余料,查询是否有余料有关的叫料任务,且未执行,则取消叫料任务,修改终点为该叫料终点
|
/// 3).如没有相关叫料任务,则正常入库
|
///
|
/// 5.空工装出库和成型机叫料任务,当申请类型为2,3,4是,需要重新生成任务
|
/// </summary>
|
/// <param name="taskNo"></param>
|
/// <param name="loc"></param>
|
/// <param name="trayCode"></param>
|
/// <param name="applyType">1.正常 2.异常</param>
|
/// <returns></returns>
|
public static string AGVApplyDest(string taskNo ,string loc ,string trayCode,string applyType)
|
{
|
LogHelper.Info($"AGV申请终点,任务号:{taskNo},当前位置:{loc},申请类型:{applyType}", "HosttoagvTask");
|
string applyDest = null;
|
try
|
{
|
WCSTask cst = WCSHelper.GetTask(taskNo);
|
if (cst != null && cst.N_B_STATE < 3)
|
{
|
WMSTask mst = WMSHelper.GetWmsTask(cst.S_OP_CODE);
|
if (mst != null && mst.N_B_STATE < 2)
|
{
|
// 防止重复申请
|
if ((applyType != "1" && !cst.S_TYPE.Contains("【异常】")) || (applyType == "1" && cst.S_END_LOC.Contains("虚拟货位")))
|
{
|
// 斜裁立库
|
if (mst.S_OP_DEF_NAME.Contains("斜裁"))
|
{
|
applyDest = applyAgvDestXC(applyType, mst, cst);
|
}
|
else
|
{
|
applyDest = applyAgvDest(applyType, loc, mst, cst);
|
}
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
WMSHelper.addAlarmRecord("系统错误","高", $"AGV申请终点,WMS内部错误,错误原因:{ex.Message}", "AGV");
|
}
|
return null;
|
}
|
|
/// <summary>
|
/// 斜裁立库任务,AGV申请终点
|
/// 1).根据RFID查询中间表,判断物料类型,如为空工装,正常入库(计算入库站台,生成预创建搬运任务)
|
/// 2).如是余料,查询是否有余料有关的叫料任务,且未执行,则取消叫料任务,修改终点为该叫料终点
|
/// </summary>
|
/// <param name="applyType"></param>
|
/// <param name="mst"></param>
|
/// <param name="cst"></param>
|
/// <returns></returns>
|
public static string applyAgvDestXC(string applyType, WMSTask mst, WCSTask cst)
|
{
|
string destLoc = null;
|
Location agvEndLoc = null;
|
Location wmsEndLoc = null;
|
if (applyType == "1")
|
{
|
if (mst.S_TYPE == "余料/空工装入库")
|
{
|
var bo = int.TryParse(mst.S_OP_DEF_CODE, out int mesId);
|
if (bo)
|
{
|
var mesTask = WMSHelper.GetLjMesTaskById(mesId);
|
if (mesTask.QTY != 0)
|
{
|
var awaitTask = WMSHelper.GetAwaitWmsTaskByMaterialCode(mesTask.MATERIAL_CODE);
|
if (awaitTask != null)
|
{
|
// 取消任务
|
ApiHelper.cancelTask(awaitTask.S_CODE);
|
// 修改终点
|
agvEndLoc = LocationHelper.GetLoc(awaitTask.S_END_LOC);
|
wmsEndLoc = agvEndLoc;
|
mst.S_TYPE = "叫料出库任务";
|
}
|
}
|
}
|
}
|
}
|
|
if (agvEndLoc == null)
|
{
|
string msg = "";
|
if (applyType == "2" || applyType == "3" || applyType == "4")
|
{
|
cst.S_TYPE = cst.S_TYPE + "【异常】";
|
msg = "工装异常";
|
}
|
|
// TODO 反馈斜裁立库异常,请求斜裁入库终点
|
agvEndLoc = null;
|
|
}
|
|
if (agvEndLoc != null)
|
{
|
destLoc = agvEndLoc.S_CODE;
|
|
cst.S_END_LOC = agvEndLoc.S_CODE;
|
cst.S_END_AREA = agvEndLoc.S_AREA_CODE;
|
WCSHelper.UpdateEndLoc(cst);
|
}
|
|
if (wmsEndLoc != null)
|
{
|
mst.S_END_LOC = wmsEndLoc.S_CODE;
|
mst.S_END_AREA = wmsEndLoc.S_AREA_CODE;
|
WMSHelper.UpdateTaskEnd(mst);
|
}
|
return destLoc;
|
}
|
|
/// <summary>
|
/// AGV申请终点
|
/// 场景:1.余料/空工装入库任务(成型机) 2.满料/空工装入库(机台) 3.满料/空工装出库异常 4.满料/空工装入库异常
|
/// </summary>
|
/// <param name="applyType">1.正常 2.RFID与任务RFID不匹配 3.物料状态不合格</param>
|
/// <param name="loc"></param>
|
/// <param name="mst"></param>
|
/// <param name="cst"></param>
|
/// <returns></returns>
|
public static string applyAgvDest(string applyType,string loc, WMSTask mst, WCSTask cst)
|
{
|
LogHelper.Info($"开始申请AGV终点", "AGV");
|
string destLoc = null;
|
Location agvEndLoc = null;
|
Location wmsEndLoc = null;
|
Location currentLoc = LocationHelper.GetLoc(loc);
|
|
// RFID 检测正常
|
if (applyType == "1")
|
{
|
// 场景:1.余料/空工装入库任务
|
// 1).根据RFID查询中间表,判断物料类型,如为空工装,正常入库(计算入库站台,生成预创建搬运任务)
|
// 2).如是余料,查询是否有余料有关的叫料任务,且未执行,则取消叫料任务,修改终点为该叫料终点
|
if (cst.S_TYPE.Contains("余料/空工装入库"))
|
{
|
LogHelper.Info($"余料/空工装入库任务,判断是否回库或发往叫料点", "AGV");
|
var mesTask = WMSHelper.GetLjMesTaskById(int.Parse(mst.S_OP_DEF_CODE));
|
if (mesTask.QTY != 0)
|
{
|
var awaitTask = WMSHelper.GetAwaitWmsTaskByMaterialCode(mesTask.MATERIAL_CODE);
|
if (awaitTask != null)
|
{
|
LogHelper.Info($"余料/空工装入库任务,存在等待的叫料任务,发往叫料点", "AGV");
|
// 取消任务
|
ApiHelper.cancelTask(awaitTask.S_CODE);
|
// 修改终点
|
agvEndLoc = LocationHelper.GetLoc(awaitTask.S_END_LOC);
|
|
cst.S_TYPE = "叫料出库任务";
|
mst.S_TYPE = mst.S_TYPE + "【叫料】";
|
}
|
}
|
}
|
|
// 场景:1.满料/空工装入库 2.余料/空工装入库
|
if (agvEndLoc == null && cst.S_TYPE.Contains("入库"))
|
{
|
LogHelper.Info($"如没有满足条件的agv终点货位,则发往立库", "AGV");
|
Container container = ContainerHelper.GetCntr(cst.S_CNTR_CODE);
|
if (container != null)
|
{
|
wmsEndLoc = WMSHelper.getInStockEndLoc(null, container.N_DETAIL_COUNT == 0 ? 0 : 1, container.N_TYPE);
|
if (wmsEndLoc != null)
|
{
|
agvEndLoc = WMSHelper.GetMinTaskTransfeLoc(wmsEndLoc.S_AREA_CODE, 1, 2); // 1.立库接驳位 1.入库 2.非直连
|
if (agvEndLoc != null)
|
{
|
LogHelper.Info($"创建立库站台到立库的预创建任务,agv终点货位:{agvEndLoc.S_CODE},立库终点货位:{wmsEndLoc.S_CODE}", "AGV");
|
// 预先生成入库站台-立库终点的搬运任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = mst.S_OP_DEF_NAME,
|
S_OP_CODE = mst.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = cst.S_CNTR_CODE,
|
S_TYPE = mst.S_TYPE,
|
S_START_LOC = agvEndLoc.S_CODE,
|
S_START_AREA = agvEndLoc.S_AREA_CODE,
|
S_END_LOC = wmsEndLoc.S_CODE,
|
S_END_AREA = wmsEndLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = 10,
|
N_B_STATE = -1,
|
T_START_TIME = DateTime.Now,
|
};
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 1);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,立库:{wmsEndLoc.S_AREA_CODE}未配置立库接驳位");
|
return null;
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到空余立库货位");
|
return null;
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到容器编码:{cst.S_CNTR_CODE}的容器");
|
return null;
|
}
|
}
|
}
|
|
// 场景:1.满料/空工装出库异常 2.满料/空工装入库异常(空工装出库异常 、满料入库异常)
|
if (applyType == "2" )
|
{
|
WCSHelper.CancelPreCreateTask(mst.S_CODE);
|
mst.S_TYPE = mst.S_TYPE + "【异常】";
|
|
// 1.异常工装优先发往异常区
|
LogHelper.Info($"异常工装优先发往异常区", "AGV");
|
agvEndLoc = WMSHelper.getAbnormalAreaLoc(currentLoc.S_AREA_CODE);
|
if (agvEndLoc != null)
|
{
|
wmsEndLoc = agvEndLoc;
|
}
|
else
|
{
|
LogHelper.Info($"异常区没有空货位,发往立库", "AGV");
|
}
|
|
// 2.异常区没有空货位,则发往立库
|
if (agvEndLoc == null)
|
{
|
LogHelper.Info($"如没有满足条件的agv终点货位,则发往立库", "AGV");
|
Container container = ContainerHelper.GetCntr(cst.S_CNTR_CODE);
|
if (container != null)
|
{
|
wmsEndLoc = WMSHelper.getInStockEndLoc(null, container.N_DETAIL_COUNT == 0 ? 0 : 1, container.N_TYPE);
|
if (wmsEndLoc != null)
|
{
|
agvEndLoc = WMSHelper.GetMinTaskTransfeLoc(wmsEndLoc.S_AREA_CODE, 1, 2); // 1.立库接驳位 1.入库 2.非直连
|
if (agvEndLoc != null)
|
{
|
LogHelper.Info($"创建立库站台到立库的预创建任务,agv终点货位:{agvEndLoc.S_CODE},立库终点货位:{wmsEndLoc.S_CODE}", "AGV");
|
// 预先生成入库站台-立库终点的搬运任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = mst.S_OP_DEF_NAME,
|
S_OP_CODE = mst.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = cst.S_CNTR_CODE,
|
S_TYPE = cst.S_TYPE + "【异常】",
|
S_START_LOC = agvEndLoc.S_CODE,
|
S_START_AREA = agvEndLoc.S_AREA_CODE,
|
S_END_LOC = wmsEndLoc.S_CODE,
|
S_END_AREA = wmsEndLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = 10,
|
N_B_STATE = -1,
|
S_B_STATE = "预创建",
|
T_START_TIME = DateTime.Now,
|
};
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 1);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
cst.S_TYPE = cst.S_TYPE + "【异常】";
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到立库接驳位");
|
return null;
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到空余立库货位");
|
return null;
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到容器编码:{cst.S_CNTR_CODE}的容器");
|
return null;
|
}
|
}
|
}
|
|
if (agvEndLoc != null && wmsEndLoc != null)
|
{
|
destLoc = agvEndLoc.S_CODE;
|
cst.S_END_LOC = agvEndLoc.S_CODE;
|
cst.S_END_AREA = agvEndLoc.S_AREA_CODE;
|
WCSHelper.UpdateEndLoc(cst);
|
|
mst.S_END_LOC = wmsEndLoc.S_CODE;
|
mst.S_END_AREA = wmsEndLoc.S_AREA_CODE;
|
WMSHelper.UpdateTaskEnd(mst);
|
}
|
|
// 重新发起新任务
|
if (applyType != "1")
|
{
|
var mesTask = WMSHelper.GetLjMesTaskByAgvorderId(mst.S_CODE);
|
if (mesTask != null)
|
{
|
if (mst.S_TYPE.Contains("叫料出库任务"))
|
{
|
LogHelper.Info($"叫料出库任务异常,再次发起叫料出库任务", "AGV");
|
callMaterial(mesTask.MATERIAL_CODE, mesTask.POSITION_ID, mesTask.ID);
|
}
|
|
// 满料下线(非直连)
|
if (mst.S_TYPE.Contains("满料/异常工装入库任务") && cst.S_TYPE.Contains("空工装出库任务"))
|
{
|
LogHelper.Info($"满料/异常工装入库任务异常,再次发起满料/异常工装入库任务", "AGV");
|
var logicConfig = WMSHelper.getLogicConfigByJtCode(mesTask.EQP);
|
if (logicConfig != null)
|
{
|
triggerItemOffLineFlow4(mesTask.POSITION_ID, mst.S_CNTR_CODE, logicConfig ,mesTask);
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"MES任务{mesTask.ID},机台号:{mesTask.EQP},未查询到逻辑线路", "AGV");
|
}
|
}
|
}
|
}
|
return destLoc;
|
}
|
|
/// <summary>
|
/// 成新机叫料
|
/// </summary>
|
/// <param name="materialCode"></param>
|
/// <param name="jtNo"></param>
|
/// <param name="mesTaskId"></param>
|
public static void callMaterial(string materialCode, string jtNo, int mesTaskId)
|
{
|
string cntrCode = "";
|
var mesTask = WMSHelper.GetLjMesTaskById(mesTaskId);
|
|
if (mesTask != null)
|
{
|
Location endLoc = WMSHelper.getCallMaterialLocCode(jtNo);
|
if (endLoc != null)
|
{
|
Location middleLoc = null;
|
Location startLoc = WMSHelper.getOutStockStartLoc(null, materialCode);
|
if (startLoc != null)
|
{
|
var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE);
|
if (locCntrRels.Count > 0)
|
{
|
cntrCode = locCntrRels[0].S_CNTR_CODE;
|
middleLoc = WMSHelper.GetTransfeRelevanceLoc(startLoc.S_AREA_CODE, 1, 2);
|
if (middleLoc != null)
|
{
|
// 1.创建成新机叫料作业
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = cntrCode,
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_TYPE = "叫料出库任务",
|
S_OP_DEF_CODE = mesTaskId.ToString(),
|
S_OP_DEF_NAME = "成型机叫料出库任务",
|
T_START_TIME = DateTime.Now,
|
};
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE,
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = middleLoc.S_CODE,
|
S_END_AREA = middleLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = 10,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
}
|
|
// 预创建二段任务
|
WCSTask twoWcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE,
|
S_START_LOC = middleLoc.S_CODE,
|
S_START_AREA = middleLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "AGV",
|
N_PRIORITY = 10,
|
T_START_TIME = DateTime.Now,
|
N_B_STATE = -1
|
};
|
WCSHelper.CreateTask(twoWcsTask);
|
WMSHelper.readLjMesCallItemTask(wmsTask.S_CODE, mesTaskId);
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,库区{startLoc.S_AREA_CODE}未查询到可用的接驳位");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,开始货位:{startLoc.S_CODE}异常,缺少容器信息");
|
}
|
}
|
else
|
{
|
mesTask.AWAIT_MSG = "库存不足";
|
WMSHelper.updateLjMesTask(mesTask);
|
WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,物料:{materialCode}库存不足");
|
}
|
}
|
}
|
|
}
|
|
/// <summary>
|
/// 成新机叫料(环带库)
|
/// 1.查询环带库物料库存
|
/// 2.查询中转库库存,根据入库时间 进行先入先出
|
/// 3.如果为环带库物料,则将mes任务写入环带库任务中间表
|
/// </summary>
|
/// <param name="materialCode"></param>
|
/// <param name="endLocCode"></param>
|
/// <param name="mesTaskId"></param>
|
public static void callMaterialXC(string materialCode, string endLocCode, int mesTaskId)
|
{
|
// 1.查询环带库物料库存
|
DateTime inStockTimeXc = DateTime.MinValue;
|
List<CntrItemRel> cntrItemRelsXc = new List<CntrItemRel>();
|
if (cntrItemRelsXc.Count > 0)
|
{
|
inStockTimeXc = cntrItemRelsXc[0].T_INBOUND_TIME;
|
}
|
|
// 2.查询中转库库存
|
DateTime inStockTime = DateTime.MinValue;
|
var cntrItemRels = WMSHelper.getZZKInventoryInfo(materialCode);
|
if (cntrItemRels.Count > 0)
|
{
|
inStockTime = cntrItemRels[0].T_INBOUND_TIME;
|
}
|
|
// 3.根据先进先出计算出库的物料是环带库 还是中转库
|
var mesTask = WMSHelper.GetLjMesTaskById(mesTaskId);
|
if (inStockTime >= inStockTimeXc)
|
{
|
//斜裁物料出库
|
if (cntrItemRelsXc.Count > 0)
|
{
|
// 4.将MES任务写入环带库任务中间表
|
WMSHelper.addLjXcTask(mesTask);
|
}
|
}
|
else
|
{
|
//中转库物料出库
|
if (cntrItemRels.Count > 0)
|
{
|
var cntrItemRel = cntrItemRels[0];
|
var locCntrRel = LocationHelper.GetLocCntrByCntr(cntrItemRel.S_CNTR_CODE);
|
if (locCntrRel != null)
|
{
|
var endLoc = LocationHelper.GetLoc(locCntrRel.S_LOC_CODE);
|
if (endLoc != null)
|
{
|
Location middleLoc = null;
|
Location startLoc = WMSHelper.getOutStockStartLoc(null, materialCode);
|
if (startLoc != null)
|
{
|
var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE);
|
if (locCntrRels.Count > 0)
|
{
|
var cntrCode = cntrItemRel.S_CNTR_CODE;
|
middleLoc = WMSHelper.GetTransfeRelevanceLoc(startLoc.S_AREA_CODE, 1, 2);
|
if (middleLoc != null)
|
{
|
// 1.创建成新机叫料作业
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = cntrCode,
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_TYPE = "叫料出库任务",
|
S_OP_DEF_CODE = mesTaskId.ToString(),
|
S_OP_DEF_NAME = "成型机叫料出库任务",
|
T_START_TIME = DateTime.Now,
|
};
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE,
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = middleLoc.S_CODE,
|
S_END_AREA = middleLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = 10,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
}
|
|
// 预创建二段任务
|
WCSTask twoWcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE,
|
S_START_LOC = middleLoc.S_CODE,
|
S_START_AREA = middleLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "AGV",
|
N_PRIORITY = 10,
|
T_START_TIME = DateTime.Now,
|
N_B_STATE = -1
|
};
|
WCSHelper.CreateTask(twoWcsTask);
|
WMSHelper.readLjMesCallItemTask(wmsTask.S_CODE, mesTaskId);
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,库区{startLoc.S_AREA_CODE}未查询到可用的接驳位");
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,开始货位:{startLoc.S_CODE}异常,缺少容器信息");
|
}
|
}
|
else
|
{
|
mesTask.AWAIT_MSG = "库存不足";
|
WMSHelper.updateLjMesTask(mesTask);
|
WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,物料:{materialCode}库存不足");
|
}
|
}
|
}
|
}
|
}
|
}
|
|
/// <summary>
|
/// 余料/空托回库
|
///
|
/// 1.查询成型机叫料终点对应的 余料/空托返回位
|
/// 2.查询mes任务中间表是否存在返料任务
|
/// 3.创建余料回库作业,创建agv搬运任务,虚拟终点
|
/// </summary>
|
/// <param name="locCode">成型机叫料终点</param>
|
/// <param name="jtNo">成型机叫料终点</param>
|
public static void returnMaterialOrEmptyTray(string locCode ,string jtNo)
|
{
|
if (locCode != null)
|
{
|
var mesTask = WMSHelper.getLjMesTaskByJtNo(jtNo);
|
if (mesTask != null)
|
{
|
createReturnTask(locCode, mesTask);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 创建余料/空工装返回任务
|
/// </summary>
|
/// <param name="locCode"></param>
|
/// <param name="mesTask"></param>
|
public static void createReturnTask(string locCode ,LjMesTask mesTask) {
|
Location startLoc = LocationHelper.GetLoc(locCode);
|
Location endLoc = new Location() { S_CODE = "虚拟货位", S_AREA_CODE = "虚拟库区" };
|
|
string suffix = "";
|
if (mesTask.PALLET_TYPE == "5" || mesTask.PALLET_TYPE == "6") {
|
suffix = "(斜裁)";
|
}
|
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = mesTask.PALLET_ID,
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_TYPE = "余料/空工装入库任务" + suffix,
|
S_OP_DEF_CODE = mesTask.ID.ToString(),
|
S_OP_DEF_NAME = "余料/空工装入库" + suffix,
|
T_START_TIME = DateTime.Now
|
};
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
// 创建一段入库任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE,
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "AGV",
|
N_PRIORITY = 99,
|
T_START_TIME = DateTime.Now,
|
};
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、接驳点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
|
WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE, mesTask.ID);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 不合格品回库
|
/// 1.创建回库任务
|
/// 2.重新发起新的叫料任务
|
/// </summary>
|
/// <param name="mst"></param>
|
/// <param name="cst"></param>
|
/// <returns></returns>
|
public static bool rejectReturnStock(WMSTask mst, WCSTask cst)
|
{
|
bool result = true;
|
|
Location startLoc = LocationHelper.GetLoc(cst.S_END_LOC);
|
Location agvEndLoc = null;
|
Location wmsEndLoc = null;
|
// 斜裁立库
|
if (mst.S_OP_DEF_NAME.Contains("斜裁"))
|
{
|
// TODO 反馈斜裁立库异常,请求斜裁入库终点
|
agvEndLoc = null;
|
wmsEndLoc = agvEndLoc;
|
|
if (agvEndLoc != null)
|
{
|
// 预先生成入库站台-立库终点的搬运任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = mst.S_OP_DEF_NAME,
|
S_OP_CODE = mst.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = cst.S_CNTR_CODE,
|
S_TYPE = "不合格品回库",
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = agvEndLoc.S_CODE,
|
S_END_AREA = agvEndLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "AGV",
|
N_PRIORITY = 10,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、接驳点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 1);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
}
|
}
|
}
|
else
|
{
|
Container container = ContainerHelper.GetCntr(cst.S_CNTR_CODE);
|
wmsEndLoc = WMSHelper.getInStockEndLoc(null, container.N_DETAIL_COUNT == 0 ? 0 : 1, container.N_TYPE);
|
if (wmsEndLoc != null)
|
{
|
agvEndLoc = WMSHelper.GetMinTaskTransfeLoc(wmsEndLoc.S_AREA_CODE, 1, 2); // 1.立库接驳位 1.入库 2.非直连
|
if (agvEndLoc != null)
|
{
|
// 预先生成入库站台-立库终点的搬运任务
|
WCSTask oneWcsTask = new WCSTask()
|
{
|
S_OP_NAME = mst.S_OP_DEF_NAME,
|
S_OP_CODE = mst.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = cst.S_CNTR_CODE,
|
S_TYPE = "不合格品回库",
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = agvEndLoc.S_CODE,
|
S_END_AREA = agvEndLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "AGV",
|
N_PRIORITY = 10,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(oneWcsTask))
|
{
|
// 起点、接驳点、终点加锁
|
LocationHelper.LockLoc(oneWcsTask.S_START_LOC, 1);
|
LocationHelper.LockLoc(oneWcsTask.S_END_LOC, 1);
|
}
|
|
// 预先生成入库站台-立库终点的搬运任务
|
WCSTask twoWcsTask = new WCSTask()
|
{
|
S_OP_NAME = mst.S_OP_DEF_NAME,
|
S_OP_CODE = mst.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = cst.S_CNTR_CODE,
|
S_TYPE = "不合格品回库",
|
S_START_LOC = agvEndLoc.S_CODE,
|
S_START_AREA = agvEndLoc.S_AREA_CODE,
|
S_END_LOC = wmsEndLoc.S_CODE,
|
S_END_AREA = wmsEndLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = 10,
|
N_B_STATE = -1,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(twoWcsTask))
|
{
|
// 起点、接驳点、终点加锁
|
LocationHelper.LockLoc(twoWcsTask.S_START_LOC, 1);
|
LocationHelper.LockLoc(twoWcsTask.S_END_LOC, 1);
|
}
|
}
|
}
|
|
var bo = int.TryParse(mst.S_OP_DEF_CODE, out int mesId);
|
if (bo)
|
{
|
var mesTask = WMSHelper.GetLjMesTaskById(mesId);
|
callMaterial(mesTask.MATERIAL_CODE, mesTask.POSITION_ID, mesTask.ID);
|
}
|
}
|
return result;
|
}
|
|
|
/// <summary>
|
/// 查询容器物料信息(中间表)
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult findTrayItemInfo(FindTrayItemInfoModel model) {
|
ResponseResult responseResult = new ResponseResult();
|
var cntrItemRels = ContainerHelper.GetCntrItemRel(model.cntrNo);
|
if (cntrItemRels != null && cntrItemRels.Count > 0) {
|
TrayItemInfo trayItemInfo = new TrayItemInfo()
|
{
|
S_SERIAL_NO = cntrItemRels[0].S_SERIAL_NO,
|
S_ITEM_CODE = cntrItemRels[0].S_ITEM_CODE,
|
S_ITEM_NAME = cntrItemRels[0].S_ITEM_NAME,
|
S_ITEM_SPEC = cntrItemRels[0].S_ITEM_SPEC,
|
S_ITEM_STATE = cntrItemRels[0].S_ITEM_STATE,
|
N_ITEM_STATE = cntrItemRels[0].N_ITEM_STATE,
|
S_BATCH_NO = cntrItemRels[0].S_BATCH_NO,
|
F_QTY = cntrItemRels[0].F_QTY,
|
S_UOM = cntrItemRels[0].S_UOM,
|
S_CNTR_CODE = cntrItemRels[0].S_CNTR_CODE,
|
D_PRD_DATE = cntrItemRels[0].D_PRD_DATE,
|
D_EXP_DATE = cntrItemRels[0].D_EXP_DATE,
|
D_EXP_DATE1 = cntrItemRels[0].D_EXP_DATE1,
|
};
|
responseResult.data = trayItemInfo;
|
}
|
return responseResult;
|
}
|
|
|
|
/// <summary>
|
/// 设备报警反馈
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult notifyAlarm(DeviceAlertorFeedbackModel model) {
|
ResponseResult responseResult = new ResponseResult();
|
WMSHelper.addAlarmRecord("设备故障", "高", $"设备号{model.deviceNo},错误信息:"+model.errMsg);
|
return responseResult;
|
}
|
|
/// <summary>
|
/// 人工手动入库
|
/// 2.根据容器号查询入库任务
|
/// 3.如果没有入库任务,记录异常
|
/// 4.进行入库
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult manualStorage(ManualStorageModel model)
|
{
|
ResponseResult responseResult = new ResponseResult();
|
|
// 查询中间表
|
var ljMesTask = WMSHelper.getLjMesTaskByCntr( model.cntrNo);
|
if (ljMesTask == null)
|
{
|
responseResult.code = 1;
|
responseResult.msg = "未查询到MES下发的入库任务";
|
return responseResult;
|
}
|
|
string taskType = "";
|
if (ljMesTask.QTY == 0)
|
{
|
taskType = "空工装人工入库";
|
}
|
else {
|
taskType = "满料工装人工入库";
|
}
|
|
var startLoc = LocationHelper.GetLoc(model.from);
|
var transfeRele = WMSHelper.GetTransfeRelevance(model.from); // 接驳位属性
|
if (transfeRele != null)
|
{
|
var endLoc = WMSHelper.getInStockEndLoc(transfeRele.S_RELE_AREA, ljMesTask.QTY);
|
if (startLoc == null)
|
{
|
responseResult.code = 1;
|
responseResult.msg = "接驳位不存在,请检查起点货位编码是否有误";
|
return responseResult;
|
}
|
|
if (endLoc == null)
|
{
|
responseResult.code = 1;
|
responseResult.msg = "立库空余库位不足";
|
return responseResult;
|
}
|
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = model.cntrNo,
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_TYPE = taskType,
|
S_OP_DEF_CODE = ljMesTask.ID.ToString(),
|
S_OP_DEF_NAME = "人工入库任务",
|
N_PRIORITY = 1,
|
T_START_TIME = DateTime.Now
|
};
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
// 创建一段入库任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE + "-WCS",
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = wmsTask.N_PRIORITY,
|
T_START_TIME = DateTime.Now,
|
};
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、接驳点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
|
WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE ,ljMesTask.ID);
|
}
|
}
|
}
|
else
|
{
|
WMSHelper.addAlarmRecord("流程异常", "中", $"接驳位:{model.from},缺少属性配置项,请联系管理进行配置");
|
responseResult.code = 1;
|
responseResult.msg = $"接驳位缺少属性配置项,请联系管理进行配置";
|
}
|
|
return responseResult;
|
}
|
|
/// <summary>
|
/// 人工出库
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult manualDelivery(ManualDeliveryModel model) {
|
ResponseResult responseResult = new ResponseResult();
|
|
// 查询中间表
|
var ljMesTask = WMSHelper.getLjMesTaskByLoc(model.to);
|
if (ljMesTask == null)
|
{
|
responseResult.code = 1;
|
responseResult.msg = "未查询到MES任务表数据";
|
return responseResult;
|
}
|
string taskType = "";
|
if (ljMesTask.QTY == 0)
|
{
|
taskType = "空工装人工出库";
|
}
|
else
|
{
|
taskType = "满料工装人工出库";
|
}
|
|
var endLoc = LocationHelper.GetLoc(model.to);
|
var transfeRele = WMSHelper.GetTransfeRelevance(model.to); // 接驳位属性
|
if (transfeRele != null)
|
{
|
var startLoc = WMSHelper.getOutStockStartLoc(transfeRele.S_RELE_AREA, model.materialCode,model.trayStatus, model.cntrNo);
|
if (endLoc == null)
|
{
|
responseResult.code = 1;
|
responseResult.msg = "接驳位不存在,请检查起点货位编码是否有误";
|
return responseResult;
|
}
|
|
if (startLoc == null)
|
{
|
responseResult.code = 1;
|
responseResult.msg = "立库库存不足";
|
return responseResult;
|
}
|
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = model.cntrNo,
|
S_CODE = WMSHelper.GenerateTaskNo(),
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_TYPE = taskType,
|
S_OP_DEF_NAME = "人工出库任务",
|
N_PRIORITY = 1,
|
T_START_TIME = DateTime.Now
|
};
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
// 创建一段入库任务
|
WCSTask wcsTask = new WCSTask()
|
{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_CNTR_CODE = wmsTask.S_CNTR_CODE,
|
S_TYPE = wmsTask.S_TYPE + "-WCS",
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = endLoc.S_CODE,
|
S_END_AREA = endLoc.S_AREA_CODE,
|
S_SCHEDULE_TYPE = "WCS",
|
N_PRIORITY = wmsTask.N_PRIORITY,
|
T_START_TIME = DateTime.Now,
|
};
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、接驳点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
|
WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE, ljMesTask.ID);
|
}
|
}
|
}
|
else {
|
WMSHelper.addAlarmRecord("流程异常", "中", $"接驳位:{model.to},缺少属性配置项,请联系管理进行配置");
|
responseResult.code = 1;
|
responseResult.msg = $"接驳位缺少属性配置项,请联系管理进行配置";
|
}
|
|
return responseResult;
|
}
|
|
/// <summary>
|
/// 取消任务
|
/// </summary>
|
/// <param name="taskNo"></param>
|
public static ResponseResult cancelTask(string taskNo) {
|
ResponseResult responseResult = new ResponseResult();
|
WMSTask wmsTask = WMSHelper.GetWmsTask(taskNo);
|
if (wmsTask != null && wmsTask.N_B_STATE == 0)
|
{
|
|
var wcsTaskList = WCSHelper.GetTaskListBySrcNo(wmsTask.S_CODE);
|
foreach (var wcsTask in wcsTaskList)
|
{
|
if (wcsTask != null && wcsTask.N_B_STATE < 3)
|
{
|
WCSHelper.Fail(wcsTask);
|
LocationHelper.UnLockLoc(wcsTask.S_START_LOC);
|
LocationHelper.UnLockLoc(wcsTask.S_END_LOC);
|
}
|
}
|
|
wmsTask.N_B_STATE = 3;
|
wmsTask.S_B_STATE = "取消";
|
wmsTask.T_END_TIME = DateTime.Now;
|
WMSHelper.UpdateTaskState(wmsTask);
|
}
|
return responseResult;
|
}
|
|
/// <summary>
|
/// 切换站台属性
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult switchStationAttribute(SwitchStationAttributeModel model)
|
{
|
ResponseResult responseResult = new ResponseResult();
|
var task = WCSHelper.GetTaskByStartOrEnd(model.locCode);
|
if (task == null)
|
{
|
var transfeRelevance = WMSHelper.GetTransfeRelevance(model.locCode); // 接驳位属性
|
LogHelper.Info($"原站台属性:{JsonConvert.SerializeObject(transfeRelevance)}", "WMS");
|
if (transfeRelevance != null && transfeRelevance.N_PROPERTY == 2)
|
{
|
if (model.signalType == "1")
|
{
|
WMSHelper.updateTransfeLocProperty(model.locCode, 0);
|
}
|
if (model.signalType == "2")
|
{
|
WMSHelper.updateTransfeLocProperty(model.locCode, 1);
|
}
|
}
|
}
|
else
|
{
|
responseResult.code = 1;
|
responseResult.msg = "接驳位存在未完成的任务,无法切换站台属性";
|
}
|
return responseResult;
|
}
|
|
/// <summary>
|
/// 货位状态反馈
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static bool locStateFeedBack(LocStateFeedBackModel model)
|
{
|
bool result = false;
|
if (model.type == "1")
|
{
|
var task = WCSHelper.GetTask(model.req_no);
|
if (task != null)
|
{
|
TaskAction taskAction = null;
|
if (model.type == "1")
|
{
|
taskAction = WCSHelper.getActionRecord(task.S_CODE, 1101);
|
}
|
if (model.type == "2")
|
{
|
taskAction = WCSHelper.getActionRecord(task.S_CODE, 1102);
|
}
|
if (taskAction != null)
|
{
|
taskAction.N_S_STATUS = 1;
|
result = WCSHelper.updateActionRecord(taskAction);
|
}
|
}
|
}
|
return result;
|
}
|
|
//----------------------------------------------------------------------------------------------------------------------------
|
public class LocModel
|
{
|
public string locCode { get; set; } // 返料货位编号
|
public string jtNo { get; set; } // 机台号
|
}
|
|
public class ApplyDest {
|
public string destLoc { get; set; } // 终点货位编码
|
}
|
public class TrayItemInfo
|
{
|
public string S_SERIAL_NO { get; set; } // 原材料批次号
|
public string S_ITEM_CODE { get; set; } // 物料编码
|
public string S_ITEM_NAME { get; set; } // 物料编码
|
public string S_ITEM_SPEC { get; set; } // 规格
|
public string S_ITEM_STATE { get; set; } = "0"; // 检验状态 0:未检验 1:合格,2:不合格
|
/// <summary>
|
/// 1:合格 2:不合格
|
/// </summary>
|
public int N_ITEM_STATE { get; set; } // 物料状态
|
public string S_BATCH_NO { get; set; } // 批次条码
|
public float F_QTY { get; set; } // 数量
|
public string S_UOM { get; set; } = ""; // 单位
|
public string S_CNTR_CODE { get; set; } // 容器
|
public string D_PRD_DATE { get; set; } // 生产日期
|
public string D_EXP_DATE { get; set; } // 最小停放日期
|
public string D_EXP_DATE1 { get; set; } // 最大停放日期
|
}
|
|
/// <summary>
|
/// 人工出库模型
|
/// </summary>
|
public class ManualDeliveryModel {
|
public string to { get; set; } // 接驳货位编码
|
public string cntrNo { get; set; } // 容器号
|
public int trayStatus { get; set; } // 托盘状态 0.正常 1.异常
|
public string materialCode { get; set; } // 物料编号 物料编码为空,表示空工装
|
}
|
|
/// <summary>
|
/// 人工入库模型
|
/// </summary>
|
public class ManualStorageModel {
|
public string from { get; set; } // 起点
|
public string cntrNo { get; set; } // 容器号
|
}
|
|
/// <summary>
|
/// 设备报警反馈模型
|
/// </summary>
|
public class DeviceAlertorFeedbackModel {
|
public string reqId { get; set; }
|
public string reqTime { get; set; }
|
public string deviceNo { get; set; } // 设备号
|
public string errCode { get; set; } // 错误码
|
public string errMsg { get; set; } // 错误信息
|
}
|
|
|
/// <summary>
|
/// 获取托盘物料信息模型
|
/// </summary>
|
public class FindTrayItemInfoModel {
|
public string reqId { get; set; }
|
public string reqTime { get; set; }
|
public string cntrNo { get; set; } // 托盘号
|
}
|
|
/// <summary>
|
/// 申请终点模型
|
/// </summary>
|
public class ApplyDestinationModel {
|
public string reqId { get; set; }
|
public string reqTime { get; set; }
|
public string taskNo { get; set; } // 任务号
|
public string loc { get; set; } // 当前货位
|
public int applyType { get; set; } // 申请类型 1:堆垛机放货异常申请新终点;2:输送线到达接驳位申请终点;3:
|
|
}
|
|
public class AGVApplyDestModel{
|
public string taskNo { get; set; } // 任务号
|
public string loc { get; set; } // 当前货位
|
public string trayCode { get; set; } // 托盘码(RFID)
|
public string applyType { get; set; } // 1.虚拟终点 2.RFID验证失败 3.RFID与任务不匹配 4.物料状态不合格
|
}
|
|
|
/// <summary>
|
/// 任务状态反馈模型
|
/// </summary>
|
public class TaskStatusFeedbackModel {
|
public string reqId { get; set; }
|
public string reqTime { get; set; }
|
public string taskNo { get; set; } // 任务号
|
public string subTaskNo { get; set; } // 子任务号
|
public int status { get; set; } // 任务状态 1:开始/执行中;2:完成;3:准备取货;4:取货完成;5:准备卸货;6:卸货完成;7:异常取消;8:强制完成
|
public string deviceNo { get; set; } // 设备号
|
public string errCode { get; set; } // 异常代码 0.无异常 1.设备故障码、2.rfid校验失败、3.取货无货、4.放货有货
|
public string loc { get; set; } // 当前货位
|
}
|
|
/// <summary>
|
/// 设备信号反馈模型
|
/// </summary>
|
public class DeviceSignalFeedbackModel
|
{
|
public string reqId { get; set; }
|
public string reqTime { get; set; }
|
public string taskNo { get; set; } // 托盘号
|
public string loc { get; set; } // 货位 上料点、下料点、读码位、称重位(必填)
|
public string cntrNo { get; set; } // 托盘号
|
public int signalType { get; set; } //请求类型 1:下线请求 2:叫料请求 3:读码请求(必填)
|
public string deviceNo { get; set; } //设备号
|
public object extData { get; set; }
|
}
|
|
/// <summary>
|
/// 叫料请求
|
/// </summary>
|
public class CallMaterialRequest
|
{
|
public string loc { get; set; } // 货位 上料点、下料点、读码位、称重位(必填)
|
}
|
|
|
/// <summary>
|
/// 下线请求
|
/// </summary>
|
public class OffLineRequest
|
{
|
public string loc { get; set; } // 货位 上料点、下料点、读码位、称重位(必填)
|
public string cntrNo { get; set; } // 托盘号
|
public string jtNo { get; set; } // 机台号
|
public bool isNormal { get; set; } //是否异常
|
}
|
|
/// <summary>
|
/// 读码请求
|
/// </summary>
|
public class ReadCodeRequest
|
{
|
public string loc { get; set; } // 货位 上料点、下料点、读码位、称重位(必填)
|
public string cntrNo { get; set; } // 托盘号
|
public string taskNo { get; set; } // 任务号
|
}
|
|
public class AddTaskModel {
|
public string From { get; set; }
|
public string To { get; set; }
|
public string No { get; set; }
|
}
|
public class TN_LocationModel {
|
public string TN_Location { get; set; }
|
}
|
public class CodeInfo {
|
/// <summary>
|
/// 生产订单内码
|
/// </summary>
|
public string FInterID { get; set; }
|
/// <summary>
|
/// 生产订单编号
|
/// </summary>
|
public string FSourceNo { get; set; }
|
/// <summary>
|
/// 批号
|
/// </summary>
|
public string FGMPBatchNo { get; set; }
|
public string FState { get; set; }
|
/// <summary>
|
/// 物料编码(内码就是编码)
|
/// </summary>
|
public string Fitemid_XK { get; set; }
|
/// <summary>
|
/// 分录id
|
/// </summary>
|
public string Fentryid { get; set; }
|
}
|
public class NoteInfo : CodeInfo {
|
public string WmsBillNo { get; set; }
|
}
|
}
|
}
|