using HH.WCS.Mobox3.NFLZ.core;
using HH.WCS.Mobox3.NFLZ.device;
using HH.WCS.Mobox3.NFLZ.dispatch;
using HH.WCS.Mobox3.NFLZ.models;
using HH.WCS.Mobox3.NFLZ.util;
using HH.WCS.Mobox3.NFLZ.wms;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Xml.Linq;
using static HH.WCS.Mobox3.NFLZ.api.OtherModel;
using static HH.WCS.Mobox3.NFLZ.dispatch.NDCApi;
using static HH.WCS.Mobox3.NFLZ.wms.WMSHelper.AddChangeModel;
namespace HH.WCS.Mobox3.NFLZ.process
{
internal class TaskProcess
{
private static HttpHelper httpHelper = new HttpHelper();
#region 任务相关
//--------------------------------------------------任务相关--------------------------------------------------
///
/// 取货卸货完成,缓存位状态更新
///
///
///
internal static void CacheBitUpdate(WCSTask mst, bool load)
{
var trayCarryCount = mst.N_CNTR_COUNT > 0 ? mst.N_CNTR_COUNT : 1;
if (load)
{
Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
LocationHelper.UnBindingLoc(mst.S_START_LOC, mst.S_CNTR_CODE.Split(',').ToList(),mst.S_TYPE);
}
else
{
Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
LocationHelper.BindingLoc(mst.S_END_LOC, mst.S_CNTR_CODE.Split(',').ToList(),mst.S_TYPE);
if (mst.S_TYPE.Contains("满托上线"))
{
//解绑物料
new SqlHelper().GetInstance().Deleteable().Where(a => mst.S_CNTR_CODE.Contains(a.S_CNTR_CODE)).ExecuteCommand();
new SqlHelper().GetInstance().Updateable().SetColumns(a => a.N_DETAIL_COUNT == 0).Where(a => mst.S_CNTR_CODE.Contains(a.S_CODE)).ExecuteCommand();
}
}
}
///
/// 任务取消,缓存位状态更新
///
///
internal static void CacheBitCancelUpdate(WCSTask mst)
{
//任务取消,取货完成前的,起点的loadingCount和终点unLoadingCount都清除,取货完成的只处理终点
if (WCSHelper.CheckActionRecordExist(mst.S_CODE, 4))
{
//根据客户现场要求,如果取货完成任务失败人工拉到终点,我们就当卸货完成处理;如果是人工拉走到其它区域,我们就解锁终点,删除托盘。
//终点绑定
CacheBitUpdate(mst, false);
LocationHelper.UnLockLoc(mst.S_END_LOC);
}
else
{
//起点终点解锁
LocationHelper.UnLockLoc(mst.S_START_LOC);
LocationHelper.UnLockLoc(mst.S_END_LOC);
}
}
///
/// 安全请求
///
///
///
///
///
internal static void OperateReq(string no, int state, string forkliftNo, string extData)
{
LogHelper.Info($"收到安全请求信号:{state},任务号:{no}");
var mst = WCSHelper.GetTask(no);
if (mst != null)
{
if (state == 1101)
{
//取货请求,允许进入取货,修改参数18为1101
DeviceProcess.quliao(mst);
}
if (state == 1103)
{
DeviceProcess.Xieliao(mst);
}
if (state == 1102 || state == 1104)
{
sendSing(mst, state);
}
}
}
internal static void sendSing(WCSTask wmsTask, int state = 0)
{
LogHelper.Info($"收到任务{wmsTask.S_CODE}信号{state},类型{wmsTask.S_TYPE}");
if(wmsTask.S_TYPE == "成品下线" || wmsTask.S_TYPE == "栈板上线")
{
int devType = wmsTask.S_TYPE == "成品下线" ? 1 : 2;
var plc = Settings.deviceInfos.Where(a => a.deviceType == devType).FirstOrDefault();
if (plc != null)
{
if (wmsTask.S_TYPE == "成品下线")
{
if (state == 1101)
{
PlcHelper.SendHex(plc.address, "3F00110D0A");
}
if (state == 1102)
{
PlcHelper.SendHex(plc.address, "3F00100d0a");
}
}
if (wmsTask.S_TYPE == "栈板上线")
{
if (state == 1103)
{
PlcHelper.SendHex(plc.address, "3F00210d0a");
}
if (state == 1104 || state == -1)
{
PlcHelper.SendHex(plc.address, "3F00200d0a");
}
}
}
else LogHelper.Info("农夫林芝-L6输送线 未配置");
}
else
{
LogHelper.Info($"{wmsTask.S_TYPE}写入复位信号");
writeSignal(wmsTask, state);
}
}
public static void writeSignal(WCSTask mst, int state = 0)
{
if (mst.S_TYPE.Contains("空托上线"))
{
LogHelper.Info($"{mst.S_TYPE}卸货完成,写入信号");
if(state == 6)
{
//根据起点判断是A口还是B口
var locCode = mst.S_END_LOC;
var devInfo = Settings.deviceInfos.Where(a => a.TN_Location.Contains(locCode)).FirstOrDefault();
if (devInfo != null)
{
var signal = devInfo.TN_Location[0] == mst.S_END_LOC ? "3F 00 10 0D 0A" : "3F 00 20 0D 0A";
if (PlcHelper.SendHex(devInfo.address, signal)) LogHelper.Info($"{mst.S_TYPE}任务卸货完成,写入信号:{signal},ip:{devInfo.address}");
}
else LogHelper.Info($"设备未找到,货位号:{mst.S_END_LOC}");
}
}
if (mst.S_TYPE.Contains("满托上线"))
{
LogHelper.Info($"{mst.S_TYPE}卸货完成,写入信号");
var locCode = mst.S_END_LOC;
var devInfo = Settings.deviceInfos.Where(a => a.TN_Location.Contains(locCode)).FirstOrDefault();
if (devInfo != null)
{
var signal = "3F 00 12 21 0D 0A";
if (state == 1104) signal = "3F 00 10 20 0D 0A";
if (PlcHelper.SendHex(devInfo.address, signal)) LogHelper.Info($"{mst.S_TYPE}任务卸货完成,写入信号:{signal},ip:{devInfo.address}");
}
else LogHelper.Info($"设备未找到,货位号:{mst.S_END_LOC}");
}
if (mst.S_TYPE.Contains("空托下线"))
{
LogHelper.Info($"{mst.S_TYPE}取货完成,写入信号");
var locCode = mst.S_START_LOC;
var devInfo = Settings.deviceInfos.Where(a => a.TN_Location.Contains(locCode)).FirstOrDefault();
if (devInfo != null)
{
var signal = "3F 00 12 21 0D 0A";
if (state == 1102) signal = "3F 00 10 20 0D 0A";
if (PlcHelper.SendHex(devInfo.address, signal)) LogHelper.Info($"{mst.S_TYPE}任务取货完成,写入信号:{signal},ip:{devInfo.address}");
}
else LogHelper.Info($"设备未找到,货位号:{mst.S_END_LOC}");
}
if (mst.S_TYPE.Contains("满托下线"))
{
LogHelper.Info($"{mst.S_TYPE}取货完成,写入信号");
if(state == 4)
{
//根据起点判断是A口还是B口
var locCode = mst.S_START_LOC;
var devInfo = Settings.deviceInfos.Where(a => a.TN_Location.Contains(locCode)).FirstOrDefault();
if (devInfo != null)
{
var signal = devInfo.TN_Location[0] == mst.S_START_LOC ? "3F 00 10 0D 0A" : "3F 00 20 0D 0A";
if (PlcHelper.SendHex(devInfo.address, signal)) LogHelper.Info($"{mst.S_TYPE}任务取货完成,写入信号:{signal},ip:{devInfo.address}");
}
else LogHelper.Info($"设备未找到,货位号:{mst.S_START_LOC}");
}
}
}
internal static void UpdateAgvNo(WCSTask mst, string forkliftNo)
{
var db = new SqlHelper().GetInstance();
mst.S_EQ_NO = forkliftNo;
db.Updateable(mst).UpdateColumns(it => new { it.S_EQ_NO }).ExecuteCommand();
}
internal static void ThirdReportStatus(WCSTask mst, int state, string forkliftNo)
{
if (state == 2)
{
TaskProcess.TASK_STATUSFunc(mst);
}
}
#region 富勒流程处理
///
/// 任务完成状态回报--1.正常任务完成回报 2.移库任务完成回报
///
///
///
internal static void TASK_STATUSFunc(WCSTask wmsTask)
{
string msg = ""; List trayList = new List();
var req = new SimpleResult();
var StartInfo = new SqlHelper().GetInstance().Queryable().Where(a => a.S_CODE == wmsTask.S_START_LOC.Trim()).First();
var EndInfo = new SqlHelper().GetInstance().Queryable().Where(a => a.S_CODE == wmsTask.S_END_LOC.Trim()).First();
List taskTrayList = new List(wmsTask.S_CNTR_CODE.Trim().Split(','));
taskTrayList.ForEach(a =>
{
if (!string.IsNullOrEmpty(a)) trayList.Add(a.Replace(",", ""));
});
string[] trayInfo = trayList.ToArray();
var url = Settings.thirdPartyUrls.Where(a => a.UrlNo == "2" && a.enable == 1).FirstOrDefault();
if (wmsTask.S_TYPE.Contains("移库"))
{
//移库任务 完成回报
var httpVerify = Settings.httpApiVerifys.Where(a => a.VerifyNo == "1" && a.Project == Settings.ProjectName && a.enable == 1).FirstOrDefault();
if (httpVerify != null)
{
var startRow = StartInfo.S_ROW.Trim();
var endRow = EndInfo.S_ROW.Trim();
var FLStartRow = new SqlHelper().GetInstance().Queryable().Where(a => a.S_LJ_ROW == startRow).First();
var FLEndRow = new SqlHelper().GetInstance().Queryable().Where(a => a.S_LJ_ROW == endRow).First();
if (FLStartRow != null && FLEndRow != null)
{
string sendMsg = JsonConvert.SerializeObject(new
{
startAreaNo = FLStartRow.S_FL_ROW.Trim(),
endAreaNo = FLEndRow.S_FL_ROW.Trim(),
trayInfo = trayInfo,
repoNo = "LJ02"
});
LogHelper.Info("sendMsg secusess:" + JsonConvert.SerializeObject(sendMsg));
req = FuLeWebPost(sendMsg, "yikuTaskStatus ", url.Url);//YKRWSD AreaRowLockState
}
}
else
{
AnalysisCompleteModel model = new AnalysisCompleteModel();
model.TrayInfo = trayInfo;
model.StartAreaNo = StartInfo.S_ROW.Trim().Replace("-XB", "");
model.EndAreaNo = EndInfo.S_ROW.Trim().Replace("-XB", "");
string sendMsg = JsonConvert.SerializeObject(model);
req = FuLeWebPost(sendMsg, "YKRWWC", url.Url);//YKRWWC YIKUTASK_STATUS
}
}
else if (wmsTask.S_TYPE.Contains("下线"))
{
var db = new SqlHelper().GetInstance();
string SrcNo = wmsTask.S_WORK_NO?.Trim();
var workInfo = db.Queryable().Where(a => a.S_WorkNo == SrcNo).First();
if (workInfo != null)
{
if (workInfo.S_ORDER_TYPE.Trim() != "无码入库")
{
//产线下线 完成回报
var httpVerify = Settings.httpApiVerifys.Where(a => a.VerifyNo == "2" && a.Project == Settings.ProjectName && a.enable == 1).FirstOrDefault();
if (httpVerify != null)
{
var endRow = EndInfo.S_ROW.Trim();
var FLEndRow = new SqlHelper().GetInstance().Queryable().Where(a => a.S_LJ_ROW == endRow).First();
if (FLEndRow != null)
{
string sendMsg = JsonConvert.SerializeObject(new
{
trayInfo = trayInfo,
workNo = wmsTask.S_WORK_NO.Trim(),
repoNo = "LJ02",
areaLoca = FLEndRow.S_FL_ROW,
});
LogHelper.Info("sendMsg secucess:" + JsonConvert.SerializeObject(sendMsg));
req = FuLeWebPost(sendMsg, "proTaskStatus", url.Url); //AreaRowLockState
}
}
else
{
ProCompleteModel model = new ProCompleteModel();
model.TrayInfo = trayInfo;
model.WorkNo = wmsTask.S_WORK_NO.Trim();
model.AreaLoca = EndInfo.S_ROW.Trim().Replace("-XB", "");
string sendMsg = JsonConvert.SerializeObject(model);
req = FuLeWebPost(sendMsg, "WGHB", url.Url);//WGHB PROTASK_STATUS
}
}
}
}
if (req != null && req.success) msg = $"TASK_STATUS:返回任务状态成功:{JsonConvert.SerializeObject(req)}!";
else msg = $"TASK_STATUS:返回任务状态失败:{JsonConvert.SerializeObject(req)}!";
LogHelper.Info(msg, "ThirdSystemLog");
}
///
/// 任务信息接口--汉和任务每个状态进行实时上传(包括任务创建时,上报 8)
///
///
internal static void GeneralInterFaceFunc(WCSTask wmsTask, string taskStatus, string forkliftNo = "")
{
string msg = "";
var req = new SimpleResult();
var db = new SqlHelper().GetInstance();
///同一条任务同种状态只上报一次
///查询任务动作表,有任务相同并且任务状态相同的,就不上报(任务状态为1还要查询车号是否存在)
bool flage = false;
var no = wmsTask.S_CODE;
var code = int.Parse(taskStatus);
if (taskStatus == "1")
{
if (forkliftNo != "0")
{
if (db.Queryable().Count(a => a.S_TASK_CODE.Trim() == no.Trim() && a.N_ACTION_CODE == code) == 2)
{
wmsTask.S_EQ_NO = forkliftNo;
flage = true;
}
}
}
else
{
flage = true;
}
if (flage)
{
if (WCSHelper.CheckActionRecordExist(wmsTask.S_CODE, 4) && taskStatus == "7") taskStatus = "2";
try
{
//获取上报接口的URL
var url = Settings.thirdPartyUrls.Where(a => a.UrlNo == "1" && a.enable == 1).FirstOrDefault();
LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_CODE},任务状态:{taskStatus},获取URL:{url}", "ThirdSystemLog");
//任务类型数据处理
string taskType = "";
var taskTypeInfo = db.Queryable().Where(a => a.taskTypeName == wmsTask.S_TYPE).First();
if (taskTypeInfo != null) taskType = taskTypeInfo.taskType;
LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_CODE},任务状态:{taskStatus},任务类型数据处理:{taskType}", "ThirdSystemLog");
//托盘物料数据处理
List cntrList = new List(wmsTask.S_CNTR_CODE.Split(','));//获取托盘数据
string itemCode = "";//物料编码
itemCode = GeneralInterFaceGetItemCodeFunc(wmsTask, db, cntrList, itemCode);
LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_CODE},任务状态:{taskStatus},物料编码:{itemCode}", "ThirdSystemLog");
List asnReferenceList = new List { };//托码数组
GeneralInterFaceGetTrayCodeFunc(wmsTask, db, asnReferenceList, cntrList);
LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_CODE},任务状态:{taskStatus},获取托盘数据:{JsonConvert.SerializeObject(asnReferenceList)}", "ThirdSystemLog");
//AGV设备信息处理
string equipmentCode = "";
string orgCode = "";
string orgName = "";
string proxyInterfaceCode = "0050";
GeneralInterFaceGetAgvDeviceInfoFunc(wmsTask, db, ref equipmentCode, ref orgCode, ref orgName, ref proxyInterfaceCode);
LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_CODE},任务状态:{taskStatus},equipmentCode:{equipmentCode},orgCode:{orgCode},orgName:{orgName},proxyInterfaceCode:{proxyInterfaceCode}", "ThirdSystemLog");
LogHelper.Info($"wmstask.t_start_time:{wmsTask.T_START_TIME}");
if (DateTime.MinValue == wmsTask.T_START_TIME)
{
wmsTask.T_START_TIME = null;
}
DateTime dateTime = taskStatus == "1" ? Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8) : taskStatus == "2" || taskStatus == "7" ? Convert.ToDateTime(wmsTask.T_END_TIME).AddHours(-8) : taskStatus == "8" ? Convert.ToDateTime(wmsTask.T_CREATE).AddHours(-8) : DateTime.UtcNow;
string createTime = GetTimeStamp(wmsTask.T_CREATE.AddHours(-8), 1, 2);
string startTime = "";
//在C#中,使用DateTimeOffset.UtcNow.ToUnixTimeSeconds()方法获取Unix时间戳时,可能会多出一个毫秒。这是因为Unix时间戳是以秒为单位的,而DateTimeOffset.UtcNow返回的是UTC时间,其精度为100纳秒。
if (wmsTask.S_WORK_MODE != "agv" && !string.IsNullOrEmpty(wmsTask.S_WORK_MODE)) startTime = wmsTask.S_WORK_MODE;
else
{
startTime = wmsTask.T_START_TIME == null ? null : GetTimeStamp(Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8), 1, 2);
if (startTime != null)
{
wmsTask.S_WORK_MODE = startTime;
db.Updateable(wmsTask).UpdateColumns(a => new { a.S_WORK_MODE }).ExecuteCommand();
}
}
string endTime = wmsTask.T_END_TIME == null ? null : GetTimeStamp(Convert.ToDateTime(wmsTask.T_END_TIME).AddHours(-8), 1, 2);
string businessTime = taskStatus == "1" ? startTime : taskStatus == "2" || taskStatus == "7" ? endTime : taskStatus == "8" ? createTime : GetTimeStamp(dateTime, 1, 2);
string dt = wmsTask.T_START_TIME == null ? null : Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8).ToString();
string mill = wmsTask.T_START_TIME == null ? null : Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8).Millisecond.ToString();
LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_CODE},任务状态:{taskStatus},任务开始时间:{wmsTask.T_START_TIME},任务转换后时间:{dt},任务号毫秒时间:{mill},转换后时间:{startTime}", "ThirdSystemLog");
string sendMsg = JsonConvert.SerializeObject(new
{
taskCode = wmsTask.S_CODE,//任务编码
taskStatus = taskStatus,//任务状态-任务创建成功传输 8
taskType = taskType,//任务类型-需要根据 配置表数据进行转换,转换为MES的任务类型
createTime = createTime,//需转换为 时间戳 wmsTask.T_CREATE
startTime = startTime,//需转换为 时间戳 wmsTask.T_START_TIME
endTime = endTime,//需转换为 时间戳 wmsTask.T_END_TIME
businessTime = businessTime,//当前任务时间-需转换为 时间戳 DateTime.Now
startAddress = wmsTask.S_START_LOC,//起点
endAddress = wmsTask.S_END_LOC,//终点
equipmentNo = wmsTask.S_EQ_NO,//车辆编号
equipmentCode = equipmentCode,//车辆铭牌-需要根据 配置表数据,通过 车辆编号以及工厂编码 查询对应车辆铭牌
orgCode = Settings.FactoryCode,//工厂编码
orgName = Settings.FactoryName,//工厂名称
sku = itemCode,//物料编码
asnReferenceDList = asnReferenceList,//托码数组 此次叉车叉的托盘喷码, 一次叉辆车,有两个编码 产线下线且非无码模式时传输
appliactionId = "MOBOX"
//proxyInterfaceCode = proxyInterfaceCode //接口唯一标识码 固定值:0050
});
//http://yst-open-zuul-qa.idc.yst.com.cn/proxy/v1/
req = FuLeWebPost(sendMsg, "generalInterface", url.Url, true);//YKRWSD AreaRowLockState
if (req != null && req.success) msg = $"GeneralInterFaceFunc:返回任务状态成功:{JsonConvert.SerializeObject(req)}!";
else msg = $"GeneralInterFaceFunc:返回任务状态失败:{JsonConvert.SerializeObject(req)}!";
}
catch (Exception ex)
{
msg = $"GeneralInterFaceFunc Error:TaskInfo:{JsonConvert.SerializeObject(wmsTask)},TaskState:{taskStatus},ErrorMsg:{ex.Message}";
}
}
LogHelper.Info(msg, "ThirdSystemLog");
}
public class ProCompleteModel
{
///
/// 仓库编码
///
public string StockNo { get; set; } = "CK001";
public string[] TrayInfo { get; set; }
public string WorkNo { get; set; }
public string AreaLoca { get; set; }
}
public class AnalysisCompleteModel
{
///
/// 仓库编码
///
public string StockNo { get; set; } = "CK001";
public string[] TrayInfo { get; set; }
public string StartAreaNo { get; set; }
public string EndAreaNo { get; set; }
}
///
/// 任务信息接口--获取物料编码
///
///
private static string GeneralInterFaceGetItemCodeFunc(WMSTask wmsTask, SqlSugarClient db, List cntrList, string itemCode)
{
//if (cntrList.Count > 0)
//{
// string SrcNo = wmsTask.S_SRC_NO?.Trim();
// // 农夫网管下发的工单,物料获取方式
// if (!string.IsNullOrEmpty(SrcNo) && wmsTask.S_TYPE.Contains("下线"))
// {
// var workInfo = db.Queryable().Where(a => a.S_WorkNo == SrcNo).First();
// if (workInfo != null) itemCode = workInfo.S_ItemCode;
// }
// // 其他的人工建立的工单,物料获取方式
// else
// {
// var cntrItemInfo = db.Queryable().Where(a => a.S_CNTR_CODE == cntrList[0]).First();
// if (cntrItemInfo != null)
// {
// //此处查询 物料表,仅限淳安获取MES物料使用,其他工厂可自行注释;因淳安入库物料是使用 物料名称+物料层数 拼接而成,因此需要 通过物料表转换为 MES 的物料编码
// //var itemInfo = db.Queryable().Where(a => a.S_ITEM_NAME == cntrItemInfo.S_ITEM_CODE).First();
// //if (itemInfo != null) itemCode = itemInfo.S_ITEM_CODE;
// itemCode = cntrItemInfo.S_ITEM_CODE;
// }
// }
//}
//
return itemCode;
}
///
/// 任务信息接口--获取托盘数据
///
///
private static void GeneralInterFaceGetTrayCodeFunc(WMSTask wmsTask, SqlSugarClient db, List asnReferenceList, List cntrList)
{
//string SrcNo = wmsTask.S_SRC_NO?.Trim();
//
////根据任务中存放的工单号,获取工单类型--因为淳安 满托下线任务包含 下线 值,因此多判断一步,减少工单表的查询
//if (!string.IsNullOrEmpty(SrcNo) && wmsTask.S_TYPE.Contains("下线"))
//{
// var workInfo = db.Queryable().Where(a => a.S_WorkNo == SrcNo).First();
// if (workInfo != null)
// {
// if (workInfo.S_ORDER_TYPE.Trim() != "无码入库")
// {
//
// if (cntrList.Count > 0)
// {
// cntrList.ForEach(a =>
// {
// if (!string.IsNullOrEmpty(a))
// asnReferenceList.Add(new asnReferenceDModel { asnReferenceD = a });
// });
// }
// }
// }
//}
}
///
/// 任务信息接口--获取AGV设备信息数据
///
///
///
///
///
///
///
private static void GeneralInterFaceGetAgvDeviceInfoFunc(WMSTask wmsTask, SqlSugarClient db, ref string equipmentCode, ref string orgCode, ref string orgName, ref string proxyInterfaceCode)
{
//if (!string.IsNullOrEmpty(wmsTask.S_AGV_NO))
//{
// var agvDeviceInfo = db.Queryable().Where(a => a.equipmentNo == wmsTask.S_AGV_NO && a.orgCode == Settings.FactoryCode).First();
// if (agvDeviceInfo != null)
// {
// equipmentCode = agvDeviceInfo.equipmentCode;
// orgCode = agvDeviceInfo.orgCode;
// orgName = agvDeviceInfo.orgName;
// proxyInterfaceCode = agvDeviceInfo.proxyInterfaceCode;
// }
//}
}
///
/// 任务信息接口--获取时间戳
///
/// 数据位数:值:32|64 含义:32位|64位
/// 获取时间类型:值:1|2 含义:1-秒级 2-毫秒级
/// 获取时间Utc类型:值:1|2 含义:1-本地时间 2-Utc时间
///
public static string GetTimeStamp(DateTime dateTime, int DataBitType, int TimeType)
{
string timeStamp = "";
//时间戳打印
TimeSpan ts = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0);//时间戳获取
double tsTime = TimeType == 1 ? ts.TotalSeconds : ts.TotalMilliseconds;//秒级|毫秒级时间获取
string TimeTypeInfo = TimeType == 1 ? "秒级" : "毫秒级";
timeStamp = DataBitType == 32 ? Convert.ToInt32(tsTime).ToString() : Convert.ToInt64(tsTime).ToString();
//double result = 0;
//result = DataBitType == 32 ? Convert.ToInt32(tsTime) : Convert.ToInt64(tsTime);
return timeStamp;
}
public class asnReferenceDModel
{
public string asnReferenceD { get; set; }
}
///
/// 库位锁定解锁回报-移库任务锁定解锁库位
///
/// 库位号-多个库位号用英文逗号隔开
/// true-锁定库位 false-解锁库位
internal static void AreaRowLockState(string AreaRow, bool state = true)
{
string msg = ""; List areaList = new List();
var req = new SimpleResult();
List taskAreaList = new List(AreaRow.Split(','));
taskAreaList.ForEach(a =>
{
if (!string.IsNullOrEmpty(a)) areaList.Add(a);
});
string[] AreaInfo = areaList.ToArray();
var url = Settings.thirdPartyUrls.Where(a => a.UrlNo == "2" && a.enable == 1).FirstOrDefault();
var httpVerify = Settings.httpApiVerifys.Where(a => a.VerifyNo == "1" && a.Project == Settings.ProjectName && a.enable == 1).FirstOrDefault();
if (httpVerify != null)
{
string sendMsg = JsonConvert.SerializeObject(new
{
areaNum = AreaInfo,
repoNo = "LJ02",
areaLock = state ? "1" : "2"
});
LogHelper.Info("sendMsg:" + JsonConvert.SerializeObject(sendMsg));
req = FuLeWebPost(sendMsg, "areaRowLockState", url.Url);//YKRWSD AreaRowLockState
}
else
{
AreaRowLockStateModel model = new AreaRowLockStateModel();
model.AreaNum = AreaInfo;
model.AreaLock = state ? "1" : "2";
string sendMsg = JsonConvert.SerializeObject(model);
req = FuLeWebPost(sendMsg, "YKRWSD", url.Url);//YKRWSD AreaRowLockState
}
if (req != null && req.success) msg = $"YKRWSD:返回库位状态成功:{JsonConvert.SerializeObject(req)}!";
else msg = $"YKRWSD:返回库位状态失败:{JsonConvert.SerializeObject(req)}!";
LogHelper.Info(msg, "ThirdSystemLog");
}
public class AreaRowLockStateModel
{
///
/// 仓库编码
///
public string StockNo { get; set; } = "CK001";
public string[] AreaNum { get; set; }
///
/// 库位锁定状态--1-锁定 2-解锁
///
public string AreaLock { get; set; }
}
#endregion
///
/// 任务拦截
///
///
///
internal static bool Intercept(WCSTask mst)
{
var result = false;
//出库任务是批量生成的,初始终点我们先给一个虚拟点,不推送。有单独的现场去判断出库缓存区光电,空了再给出库任务分配终点
if (mst.S_END_LOC.Trim() == "出库虚拟点")
{
result = true;
}
return result;
}
///
/// 任务状态更新处理
///
///
///
internal static void OperateStatus(WCSTask mst, int state)
{
if (state == 4)
{
claimGoodsTime(mst, state);
CacheBitUpdate(mst, true);
EmptyTask(mst);
}
if (state == 6)//卸货完成
{
claimGoodsTime(mst, state);
CacheBitUpdate(mst, false);
}
if (state == 7)
{
CacheBitCancelUpdate(mst);
}
}
///
/// 瓶坯瓶盖机满托下线后生成空托上线任务
///
///
///
public static void EmptyTask(WCSTask mst)
{
//瓶盖注塑机空托上线,若即产急用库区没有多余的空托,则在非即产急用空托区拿空托
var db = new SqlHelper().GetInstance();
Location startLoca = null;
if (mst.S_TYPE.Contains("满托下线"))
{
LogHelper.Info($"空托任务生成处理,任务类型:{mst.S_TYPE}");
string areaName = mst.S_TYPE.Contains("库存") ? "瓶坯非即产空框" : "瓶坯即产空框";
var areaInfo = Settings.areaInfos.Where(a => a.areaName == areaName && a.enable == 1).First();
if(areaInfo != null)
{
startLoca = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM > 0 && a.S_LOCK_STATE == "无").OrderBy(a => a.N_ROW).First();
if (startLoca != null)
{
LogHelper.Info("startLoca" + JsonConvert.SerializeObject(startLoca));
string taskType = "";
if (mst.S_TYPE == "注塑即产满托下线(瓶坯)") taskType = "注塑即产空托上线(瓶坯)";
if (mst.S_TYPE == "注塑库存满托下线(瓶坯)") taskType = "注塑库存空托上线(瓶坯)";
var cntrInfo = db.Queryable().Where(a => a.S_LOC_CODE == startLoca.S_CODE).First();
if (cntrInfo != null)
{
WMSHelper.CreateOpTask(startLoca.S_CODE, mst.S_START_LOC, "出库", taskType, cntrInfo.S_CNTR_CODE);
}
else LogHelper.Info($"未绑定托盘,货位号:{startLoca.S_CODE}");
}
}
else
{
LogHelper.Info($"瓶坯空托未配置");
}
}
if (mst.S_TYPE.Contains("空托下线"))
{
LogHelper.Info($"满托任务生成处理,任务类型:{mst.S_TYPE}");
string startArea = "";
LinZhiBCPWorkOrder bcpW = null;
bcpW = db.Queryable().Where(a => a.S_WorkNo == mst.S_WORK_NO && a.S_WorkState == "执行中").First();
LogHelper.Info($"满托任务生成处理,工单:{JsonConvert.SerializeObject(bcpW)}");
if (mst.S_TYPE.Contains("瓶盖"))
{
//瓶盖无即产即用和非即产即用
var bcpInfo = Settings.areaInfos.Where(a => a.areaName == "瓶盖非即产满框" && a.enable == 1).FirstOrDefault();
if (bcpInfo != null)
{
startLoca = DeviceProcess.getFDSXArea(db, bcpW, bcpInfo.areaCode);
}
}
else
{
if (bcpW.S_UsingNow == "Y")
{
LogHelper.Info($"瓶坯即产满框 查找");
startArea = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产满框" && a.enable == 1).FirstOrDefault().areaCode;
startLoca = DeviceProcess.getFDSXArea(db, bcpW, startArea);
}
else
{
LogHelper.Info($"瓶坯翻斗机非即产满框 查找");
string areaName = bcpW.S_PLineNo.Split('-')[1].Substring(0, 1) + "号瓶坯翻斗机非即产满框";
startArea = Settings.areaInfos.Where(a => a.areaName == areaName && a.enable == 1).FirstOrDefault().areaCode;
startLoca = DeviceProcess.getFDSXArea(db, bcpW, startArea);
}
}
if (startLoca != null)
{
LogHelper.Info("startLoca" + JsonConvert.SerializeObject(startLoca));
string taskType = "";
if (mst.S_TYPE == "翻斗机即产空托下线(瓶坯)") taskType = "翻斗机即产满托上线(瓶坯)";
if (mst.S_TYPE == "翻斗机库存空托下线(瓶坯)") taskType = "翻斗机库存满托上线(瓶坯)";
if (mst.S_TYPE == "翻斗机库存空托下线(瓶盖)") taskType = "翻斗机库存满托上线(瓶盖)";
var cntrInfo = db.Queryable().Where(a => a.S_LOC_CODE == startLoca.S_CODE).First();
if (cntrInfo != null)
{
WMSHelper.CreateOpTask(startLoca.S_CODE, mst.S_START_LOC, "出库", taskType, cntrInfo.S_CNTR_CODE,"","",bcpW.S_WorkNo);
}
else LogHelper.Info($"未绑定托盘,货位号:{startLoca.S_CODE}");
}
}
}
private static void claimGoodsTime(WCSTask mst, int state)
{
//将取货完成时间存入中间表
var db = new SqlHelper().GetInstance();
if (state == 6 && (mst.S_TYPE == "栈板上线" || mst.S_TYPE.Contains("空托上线") || mst.S_TYPE.Contains("满托上线")))
{
LogHelper.Info($"任务{mst.S_TYPE}卸货时间存入中间表,当前时间:{DateTime.Now}");
var cgInfo = db.Queryable().Where(a => a.Bit == mst.S_END_LOC).First();
if (cgInfo != null)
{
cgInfo.time = DateTime.Now;
if (db.Updateable(cgInfo).UpdateColumns(a => new { a.time }).ExecuteCommand() > 0) LogHelper.Info($"数据更改成功,终点:{mst.S_END_LOC}");
}
else
{
CGTTable cg = new CGTTable
{
Bit = mst.S_END_LOC,
time = DateTime.Now,
};
if (db.Insertable(cg).ExecuteCommand() > 0) LogHelper.Info($"数据插入成功,终点:{mst.S_END_LOC}");
}
}
if (state == 4 && (mst.S_TYPE.Contains("空托下线") || mst.S_TYPE.Contains("满托下线")))
{
LogHelper.Info($"任务{mst.S_TYPE}取货时间存入中间表,当前时间:{DateTime.Now},点位:{mst.S_START_LOC}");
var cgInfo = db.Queryable().Where(a => a.Bit == mst.S_START_LOC).First();
if (cgInfo != null)
{
cgInfo.time = DateTime.Now;
if (db.Updateable(cgInfo).UpdateColumns(a => new { a.time }).ExecuteCommand() > 0) LogHelper.Info($"数据更改成功,起点:{mst.S_START_LOC}");
}
else
{
CGTTable cg = new CGTTable
{
Bit = mst.S_START_LOC,
time = DateTime.Now,
};
if (db.Insertable(cg).ExecuteCommand() > 0) LogHelper.Info($"数据插入成功,起点:{mst.S_START_LOC}");
}
}
}
private static object locLocker = new object();
///
/// 堆叠库区出入库任务申请
///
///
///
///
///
///
///
///
///
internal static bool ApplyTN_Task(Location ls, ref List cntrs, string area, string itemCode, string itemBatch, string taskType, bool insStock = true)
{
var result = false;
lock (locLocker)
{
try
{
if (insStock)
{
Console.WriteLine($"MoboxHelperCreateTask: {area}-{itemCode}-{itemBatch}-{taskType}");
var endTN_Location = GetLocation4In(area, itemCode, itemBatch, 3);
if (endTN_Location != null)
{
var endLayer = endTN_Location.N_CURRENT_NUM == 0 ? 1 : 2;
var taskNo = DateTime.Now.Ticks.ToString();
result = TaskProcess.CreateTransport(ls.S_CODE, endTN_Location.S_CODE, taskType, cntrs, 1, endLayer, 3, 70);
}
else
{
Console.WriteLine($"MoboxHelperCreateTask: 未找到终点货位");
}
}
else
{
var startTN_Location = GetLocation4Out(area, itemCode, itemBatch, 3);
if (startTN_Location != null)
{
var startLayer = startTN_Location.N_CURRENT_NUM <= 3 ? 1 : 2;
var taskNo = DateTime.Now.Ticks.ToString();
var carryCount = startTN_Location.N_CURRENT_NUM > 3 ? startTN_Location.N_CURRENT_NUM - 3 : startTN_Location.N_CURRENT_NUM;
//出库要从起点获取托盘
var cntrList = LocationHelper.GetLocCntr(startTN_Location.S_CODE);
if (cntrList.Count == startTN_Location.N_CURRENT_NUM)
{
cntrs = cntrList.OrderByDescending(a => a.T_CREATE).Take(carryCount).Select(a => a.S_CNTR_CODE.Trim()).ToList();
result = TaskProcess.CreateTransport(startTN_Location.S_CODE, ls.S_CODE, taskType, cntrs, startLayer, 1, carryCount, 65);
}
else
{
Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("MoboxHelperCreateTask:" + ex.Message);
LogHelper.Error("MoboxHelperCreateTask:" + ex.Message, ex);
}
}
return result;
}
private static Location GetLocation4Out(string area, string itemCode, string itemBatch, int v)
{
throw new NotImplementedException();
}
private static Location GetLocation4In(string area, string itemCode, string itemBatch, int v)
{
throw new NotImplementedException();
}
///
/// 普通货架区的出入库申请
///
///
///
///
///
///
///
///
internal static bool ApplyNormalTN_Task(Location ls, ref List cntrs, string area, string taskType, string itemCode, bool insStock = true)
{
var result = false;
lock (locLocker)
{
try
{
if (insStock)
{
Console.WriteLine($"MoboxHelperCreateTask: {area}-{taskType}");
var endTN_Location = new Location();
if (endTN_Location != null)
{
var taskNo = DateTime.Now.Ticks.ToString();
result = TaskProcess.CreateTransport(ls.S_CODE, endTN_Location.S_CODE, taskType, cntrs, 70);
}
else
{
Console.WriteLine($"MoboxHelperCreateTask: 未找到终点货位");
}
}
else
{
var startTN_Location = new Location();
if (startTN_Location != null)
{
//出库要从起点获取托盘
var cntrList = LocationHelper.GetLocCntr(startTN_Location.S_CODE);
if (cntrList.Count == startTN_Location.N_CURRENT_NUM)
{
result = TaskProcess.CreateTransport(startTN_Location.S_CODE, ls.S_CODE, taskType, new List { cntrList[0].S_CNTR_CODE }, 65);
}
else
{
Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("MoboxHelperCreateTask:" + ex.Message);
LogHelper.Error("MoboxHelperCreateTask:" + ex.Message, ex);
}
}
return result;
}
///
/// 推送任务
///
///
internal static bool SendTask(WCSTask mst)
{
var result = false;
var db = new SqlHelper().GetInstance();
if (mst.N_B_STATE == 0)
{
try
{
int TsNo = 1;//下发任务类型:默认-1 坯盖-6 成品任务-5
var Extend1 = "0";//取货站点
var Extend2 = "0";//卸货站点
string Extend3 = "";//功能码 16进制转10进制
string Extend4 = "";//坯盖:托盘类型 即产即用1,非即产即用2 不区分为1 成品:取卸货层数(先单独转换为16进制,再拼接转换为10进制)
string Extend5 = "";//物料高度(品相) 根据工单物料到物料表获取下发TS的物料高度
string Extend6 = "";//托盘版型 备注:小板 1,集化板 2,小板超托 3,集化板超托 4 根据工单版型转换为对应的值
string Extend7 = "";//起点列
string Extend8 = "";//终点列
int startLayer = mst.N_START_LAYER;// 起点取货层数
int endLayer = mst.N_END_LAYER;// 终点卸货层数
string workNo = mst.S_WORK_NO;// 工单号
string trayType = mst.S_NOTE;//托盘类型-根据各自现场情况获取
var taskType = mst.S_TYPE;// 任务类型
// 获取起终点的AGV站点 查询 扩展货位表 S_PICKUP_POINT-点位层数 S_LOC_CODE-货位编码 GetAgvSite-标准获取扩展货位表数据的方法
//Extend1 = LocationHelper.GetAgvSite(mst.S_START_LOC, startLayer.ToString());
//Extend2 = LocationHelper.GetAgvSite(mst.S_END_LOC, endLayer.ToString());
//二期成品任务类型(将 成品车间 任务类型加入到此数组中,即可根据 任务类型 区分车间,并获取对应的TS参数)
string[] ConveryTaskList = new string[] { "成品下线", "栈板上线", "零头下线" };
if (ConveryTaskList.Contains(taskType) || taskType.Contains("移库"))
{
TsNo = 5;
if (taskType.Contains("栈板上线"))
{
Extend1 = db.Queryable().Where(a => a.S_CODE == mst.S_START_LOC && a.N_LAYER == mst.N_START_LAYER).First().S_AGV_SITE;
Extend2 = db.Queryable().Where(a => a.S_CODE == mst.S_END_LOC && a.N_LAYER == mst.N_END_LAYER).First().S_AGV_SITE;
var startLoc = db.Queryable().Where(a => a.S_CODE == mst.S_START_LOC).First();
var endLoc = db.Queryable().Where(a => a.S_CODE == mst.S_END_LOC).First();
int startCol = int.Parse(startLoc.N_COL.ToString());
int endCol = int.Parse(endLoc.N_COL.ToString());
Extend7 = (startCol - 1).ToString();
Extend8 = (endCol - 1).ToString();
}
else
{
// 成品任务下发参数获取
var startLoc = db.Queryable().Where(a => a.S_CODE == mst.S_START_LOC).First();
var endLoc = db.Queryable().Where(a => a.S_CODE == mst.S_END_LOC).First();
int startCol = int.Parse(startLoc.N_COL.ToString());
int endCol = int.Parse(endLoc.N_COL.ToString());
var startLocInfo = db.Queryable().Where(a => a.S_AREA_CODE == startLoc.S_AREA_CODE && a.N_ROW == startLoc.S_ROW && a.S_START_COL <= startCol && a.S_END_COL >= startCol).First();
var endLocInfo = db.Queryable().Where(a => a.S_AREA_CODE == endLoc.S_AREA_CODE && a.N_ROW == endLoc.S_ROW && a.S_START_COL <= endCol && a.S_END_COL >= endCol).First();
if (startLocInfo != null)
{
Extend1 = mst.N_START_LAYER == 1 ? startLocInfo.S_First_Bit : startLocInfo.S_Second_Bit;
if (trayType.Contains("集化板")) Extend1 = Extend1 + 2;
Extend7 = (startCol - startLocInfo.S_START_COL).ToString();
}
else LogHelper.Info($"任务异常:{mst.S_CODE},自由线段表无可用起点货位数据。起点货位编码:{mst.S_START_LOC}");
if (endLocInfo != null)
{
Extend2 = mst.N_END_LAYER == 1 ? endLocInfo.S_First_Bit : endLocInfo.S_Second_Bit;
Extend8 = (endCol - endLocInfo.S_START_COL).ToString();
}
else LogHelper.Info($"任务异常:{mst.S_CODE},自由线段表无可用终点货位数据。终点货位编码:{mst.S_END_LOC}");
// 其他功能码可以根据任务类型自行添加(此处仅示例 移库 功能码获取方式,如果有更好的方式,可以自行修改)
if (taskType.Contains("移库")) Extend3 = Convert.ToInt32("20", 16).ToString();
}
// 获取成品工单数据(查询 成品工单表)
if (taskType.Contains("移库"))
{
var workInfo = db.Queryable().Where(a => a.S_WorkNo == workNo).First();
if (workInfo != null)
{
LogHelper.Info($"{workInfo.S_ORDER_TYPE}");
// 获取下发TS物料层数数据(查询 物料表)
if (workInfo.S_ORDER_TYPE.Contains("移库"))
{
LogHelper.Info($"物料编码:{mst.S_ITEM_CODE},栈板类型:{trayType},物料规格:{workInfo.S_ItemLayer}");
var itemInfo1 = db.Queryable().Where(a => a.S_ITEM_CODE == mst.S_ITEM_CODE && a.S_TRAY_TYPE == trayType && a.S_ITEM_MODEL == workInfo.S_ItemLayer).First();
if (itemInfo1 != null)
{
Extend5 = itemInfo1.S_ITEM_LAYER;
}
else
{
LogHelper.Info($"物料表未维护信息,物料编码:{mst.S_ITEM_CODE},栈板类型:{trayType},物料规格:{workInfo.S_ItemLayer}");
}
//if (workInfo.S_ORDER_TYPE == "无码入库" && endLayer == 1) Extend5 = "";
}
// 根据工单中托盘类型转换为对应的下发TS参数数据
LogHelper.Info($"S_TRAY_TYPE:{trayType}");
LogHelper.Info($"Extend5:{Extend5}");
int x = 0;
if (trayType == "小板") x = 1;
if (trayType == "集化板") x = 2;
if (trayType == "小板超托") x = 3;
if (trayType == "集化板超托") x = 4;
Extend6 = x.ToString();
}
}
else
{
var workInfo = db.Queryable().Where(a => a.S_WorkNo == workNo).First();
if (workInfo != null)
{
LogHelper.Info($"{workInfo.S_ORDER_TYPE}");
// 获取下发TS物料层数数据(查询 物料表)
if (workInfo.S_ORDER_TYPE.Contains("下线") || workInfo.S_ORDER_TYPE == "无码入库")
{
var itemInfo1 = db.Queryable().Where(a => a.S_ITEM_CODE == workInfo.S_ItemCode && a.S_TRAY_TYPE == trayType && a.S_ITEM_MODEL == workInfo.S_ItemLayer).First();
if (itemInfo1 != null)
{
Extend5 = itemInfo1.S_ITEM_LAYER;
}
//if (workInfo.S_ORDER_TYPE == "无码入库" && endLayer == 1) Extend5 = "";
}
// 根据工单中托盘类型转换为对应的下发TS参数数据
LogHelper.Info($"S_TRAY_TYPE:{trayType}");
int x = 0;
if (trayType == "小板") x = 1;
if (trayType == "集化板") x = 2;
if (trayType == "小板超托") x = 3;
if (trayType == "集化板超托") x = 4;
Extend6 = x.ToString();
}
}
// 获取 任务参数4 DATA 数据
string startLayerValue = Convert.ToString(startLayer, 16).ToUpper();
string endLayerValue = Convert.ToString(endLayer, 16).ToUpper();
//Extend4 = Convert.ToInt32(startLayerValue + endLayerValue, 16).ToString();
Extend4 = ((startLayer * 16) + endLayer).ToString();
}
else
{
TsNo = 1;
// 坯盖任务下发参数获取
// 获取起终点的AGV站点
Extend1 = db.Queryable().Where(a => a.S_CODE == mst.S_START_LOC).First().S_AGV_SITE;
Extend2 = db.Queryable().Where(a => a.S_CODE == mst.S_END_LOC).First().S_AGV_SITE;
if (mst.N_START_LAYER > 1)
{
if(mst.S_TYPE != "瓶坯非即产空框入库" && mst.S_TYPE != "瓶坯接驳位入库" && mst.S_TYPE != "瓶盖空托入库")
{
Extend1 = db.Queryable().Where(a => a.S_LOC_CODE == mst.S_START_LOC && a.N_LAYER == mst.N_START_LAYER).First().S_AGV_SITE;
}
}
if (mst.N_END_LAYER > 1)
{
Extend2 = db.Queryable().Where(a => a.S_LOC_CODE == mst.S_END_LOC && a.N_LAYER == mst.N_END_LAYER).First().S_AGV_SITE;
}
if(mst.S_TYPE == "瓶坯非即产补满框" || mst.S_TYPE == "瓶盖非即产补满框大包装" || mst.S_TYPE == "瓶坯非即产补空框" || mst.S_TYPE == "瓶盖非即产补空框" || mst.S_TYPE == "注塑即产满托下线(瓶坯)")
{
Extend2 = Settings.dXSites.Where(it => it.loc == mst.S_END_LOC).First().site.ToString();
}
if(mst.S_TYPE == "接驳位入库")
{
if(mst.S_CNTR_CODE.Split(',').ToList().Count != 2)
{
Extend1 = db.Queryable().Where(a => a.S_LOC_CODE == mst.S_START_LOC && a.N_LAYER == 1).First().S_AGV_SITE;
}
}
Extend3 = "0";
// 获取 任务参数4 DATA 数据
string startLayerValue = Convert.ToString(startLayer, 16).ToUpper();
string endLayerValue = Convert.ToString(endLayer, 16).ToUpper();
//Extend4 = Convert.ToInt32(startLayerValue + endLayerValue, 16).ToString();
Extend4 = ((startLayer * 16) + endLayer).ToString();
//Extend4 = db.Queryable().Where(a => a.S_WorkNo == workNo).First().S_UsingNow == "N" ? "2" : "1";
//瓶坯注塑机站点根据配置文件获取
//if (taskType.Contains("注塑") && taskType.Contains("瓶坯"))
//{
// var devInfo = Settings.deviceInfos.Where(a => (a.TN_Location.Contains(mst.S_START_LOC) || a.TN_Location.Contains(mst.S_END_LOC)) && a.enable == 1).FirstOrDefault();
// string machine = (devInfo.TN_Location[0] == mst.S_START_LOC || devInfo.TN_Location[0] == mst.S_END_LOC) ? "A" : "B";
// string machineTwo = devInfo.deviceName.Split('-')[1] + machine;
// LogHelper.Info($"机台:{machineTwo}");
// var siteInfo = Settings.pPZSJSites.Where(a => a.siteName == machineTwo && a.enable == 1).FirstOrDefault();
// if (siteInfo != null)
// {
// if (taskType.Contains("空托上线"))
// {
// //改变终点站点
// Extend2 = siteInfo.site[1];
// }
// else
// {
// //改变起点站点
// Extend1 = siteInfo.site[0];
// }
// }
// else LogHelper.Info("配置文件未配置瓶坯注塑机站点");
//}
}
Console.WriteLine($"[SendTask]:TaskNo={mst.S_CODE.Trim()},start={Extend1},end={Extend2}");
LogHelper.Info($"[SendTask]:TaskNo={mst.S_CODE.Trim()},start={Extend1},end={Extend2}");
bool action = true;
//var dic = new Dictionary();
////var dic1 = new Dictionary();
////dic.Add("Pri", mst.N_PRIORITY.ToString());
////dic.Add("No", mst.S_CODE.Trim());
//dic.Add("From", Extend1);
//dic.Add("To", Extend2);
//dic.Add("Func", Extend3);
//dic.Add("Data", Extend4);
//
//if (ConveryTaskList.Contains(taskType) || taskType.Contains("移库"))
//{
// dic.Add("ItemHeight", Extend5);
// dic.Add("CntrType", Extend6);
// dic.Add("FromCol", Extend7);
// dic.Add("ToCol", Extend8);
// if (taskType.Contains("移库") || taskType.Contains("成品下线") || taskType.Contains("零头下线"))
// {
// LogHelper.Info($"移库:Extend5:{Extend5},Extend6:{Extend6},Extend7:{Extend7},Extend8:{Extend8},");
// if (Extend5 == "" || Extend6 == "" || Extend7 == "" || Extend8 == "")
// {
// action = false;
// }
// }
//}
var dic = new List
{
new param() { name = "From", value = Extend1 },
new param() { name = "To", value = Extend2 },
new param() { name = "Func", value = Extend3 },
new param() { name = "Data", value = Extend4 }
};
if (ConveryTaskList.Contains(taskType) || taskType.Contains("移库"))
{
dic.Add(new param(){name = "ItemHeight", value = Extend5});
dic.Add(new param(){name = "CntrType", value = Extend6});
dic.Add(new param(){name = "FromCol", value = Extend7});
dic.Add(new param(){name = "ToCol", value = Extend8});
if (taskType.Contains("移库") || taskType.Contains("成品下线") || taskType.Contains("零头下线"))
{
LogHelper.Info($"移库:Extend5:{Extend5},Extend6:{Extend6},Extend7:{Extend7},Extend8:{Extend8},");
if (Extend5 == "" || Extend6 == "" || Extend7 == "" || Extend8 == "")
{
action = false;
}
}
}
if (action)
{
var res = new AgvApiResult();
//res = NDC.AddNewOrderNew(TsNo,mst.N_PRIORITY,mst.S_CODE, dic);
res = NDCApi.AddOrderNew(TsNo, mst.N_PRIORITY, mst.S_CODE,dic);
if (res != null && (res.err_code == 0 || res.err_code == 50009))
{
mst.N_B_STATE = 1;
WCSHelper.UpdateStatus(mst, "已推送");
result = true;
}
}
}
catch (Exception ex)
{
LogHelper.Error($"SendTaskStandard Error:{ex.Message}", ex);
}
//mst.N_B_STATE = 1;
//WCSHelper.UpdateStatus(mst, "已推送");
//result = true;
}
return result;
}
///
/// 创建搬运任务
///
///
///
///
///
///
///
///
///
///
public static bool CreateTransport(string start, string end, string taskType, List cntrs, int startLayer, int endLayer, int trayCarryCount = 1, int priority = 1)
{
var result = false;
//批次号存托盘号,1~3个托盘
var trayCodes = string.Join(",", cntrs);
var taskNo = DateTime.Now.Ticks.ToString();
var res = WCSHelper.CreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, trayCodes, trayCarryCount, startLayer, endLayer);
if (res)
{
result = true;
//任务创建成功,起点货位出库锁定,终点货位入库锁定
LocationHelper.LockLoc(start, 1);
LocationHelper.LockLoc(end, 2);
}
return result;
}
public static bool CreateTransport(string start, string end, string taskType, List cntrs, int priority = 1)
{
var result = false;
//批次号存托盘号,1~3个托盘
var trayCodes = string.Join(",", cntrs);
var taskNo = DateTime.Now.Ticks.ToString();
var res = WCSHelper.CreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, trayCodes, 1, 1, 1);
if (res)
{
result = true;
LocationHelper.LockLoc(start, 2);
LocationHelper.LockLoc(end, 1);
}
return result;
}
#endregion
///
/// 半成品出入库
///
///
///
///
///
///
public static Location BCPInOrOut(SqlSugarClient db, bool action, string areaName,string itemCode)
{
Location result = null;
if (action)
{
//瓶盖库区,两层密集型库区 空满在同一个库区,需要区分不同排
var areaInfo = Settings.areaInfos.Where(a => a.areaName.Contains(areaName) && a.enable == 1).OrderByDescending(a => a.pri).ToList();
if (areaInfo.Count > 0)
{
foreach(var it in areaInfo)
{
//库区货位约定:列号越小越靠里
LogHelper.Info($"入库算法01:area:{it.areaCode},itemCode:{itemCode}");
try
{
if (result == null)
{
var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == it.areaCode && a.N_CURRENT_NUM > 0).OrderBy(a => a.N_ROW).OrderByDescending(a => a.N_COL)
.PartitionBy(a => a.N_ROW).Take(1)
.ToList();
if (locInfo.Count > 0)
{
if(areaName == "瓶坯即产满框缓存")
{
locInfo = locInfo.Where(a => a.N_ROW == 1 || a.N_ROW == 2).ToList();
}
LogHelper.Info($"入库算法02:查询到可入货位的数量为:{locInfo.Count}");
foreach (var a in locInfo)
{
LogHelper.Info($"入库算法03:查询货位:{a.S_CODE},锁状态:{a.S_LOCK_STATE},当前数量:{a.N_CURRENT_NUM}");
//去掉当前货位有锁,或者为空托的货位
if (a.S_LOCK_STATE == "无")
{
string endItemCode = "";
var endCntrInfo = db.Queryable().Where(b => b.S_LOC_CODE == a.S_CODE).First();
if (endCntrInfo != null)
{
var endItemInfo = db.Queryable().Where(b => b.S_CNTR_CODE == endCntrInfo.S_CNTR_CODE).First();
if (endItemInfo != null)
{
endItemCode = endItemInfo.S_ITEM_CODE + endItemInfo.S_BATCH_NO;
}
}
else
{
LogHelper.Info($"终点货位未绑定托盘信息");
continue;
}
LogHelper.Info($"入库算法04:查询到当前货位绑定的物料编码为:{endItemCode}");
//判断是否和当前货位的物料编码相同
if (itemCode == endItemCode)
{
//查询当前排是否可入(判断是是否有入库锁和出库锁)
var lockInfo = db.Queryable().Where(b => b.S_AREA_CODE == a.S_AREA_CODE && b.N_ROW == a.N_ROW && (b.S_LOCK_STATE == "入库锁" || b.S_LOCK_STATE == "出库锁")).First();
if (lockInfo == null)
{
//当前排无任务
if (a.N_CURRENT_NUM < a.N_CAPACITY) result = a;
else
{
//查询后面当前货位后一个
result = db.Queryable().Where(b => b.S_AREA_CODE == a.S_AREA_CODE && b.N_ROW == a.N_ROW && b.N_COL > a.N_COL && b.N_CURRENT_NUM < b.N_CAPACITY && b.S_LOCK_STATE == "无").OrderBy(b => b.N_COL).First();
}
if (result != null)
{
break;
}
}
else
{
LogHelper.Info($"入库算法05:查询到当前排有锁,排号:{a.N_ROW}");
}
}
}
}
}
else
{
LogHelper.Info($"入库算法02:未查询到可入货位");
}
if (result == null)
{
//todo 还需要判断锁
#region 查找所有数量是空的排
LogHelper.Info($"入库算法06:无可用货位,获取空排货位。", "WMSAlgoRithm");
//2.0 简化查询只查每一排第一列
var list = db.Queryable().Where(a => a.S_AREA_CODE == it.areaCode).OrderBy(a => a.N_ROW).OrderBy(a => a.N_COL).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList();
//2.1 选一个空排
if (list.Count > 0)
{
LogHelper.Info($"入库算法06:无可用货位,获取空排货位数量为:{list.Count}。", "WMSAlgoRithm");
for (int i = 0; i < list.Count; i++)
{
LogHelper.Info($"入库算法07:获取空排货位:货位编码:{list[i].S_CODE.Trim()},当前数量:{list[i].N_CURRENT_NUM},排号:{list[i].N_ROW},库区编码:{list[i].S_AREA_CODE.Trim()}", "WMSAlgoRithm");
if (list[i].S_LOCK_STATE.Trim().Contains("无"))
{
//二次校验当前排所有货位都是空的,防止系统数据错乱
int row = list[i].N_ROW;
string areaCode = list[i].S_AREA_CODE.Trim();
var lockInfo = db.Queryable().Where(b => b.S_AREA_CODE == areaCode && b.N_ROW == row && (b.S_LOCK_STATE == "入库锁" || b.S_LOCK_STATE == "出库锁")).First();
if (lockInfo == null)
{
var locInfo1 = db.Queryable().Where(a => a.S_AREA_CODE == areaCode && a.N_ROW == row).Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First();
if (locInfo1 != null)
{
LogHelper.Info($"{locInfo1.sum},row:{row}");
if (locInfo1.sum == 0)
{
//空排
result = list[i];
break;
}
}
else LogHelper.Info("未找到该排");
}
else
{
LogHelper.Info("该排有锁");
}
}
}
}
else LogHelper.Info($"未获取到空排,库区编码:{it.areaCode}");
#endregion
}
if(result != null)
{
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine("GetLocationIn:" + ex.Message + ex.StackTrace);
LogHelper.Error("GetLocationIn:" + ex.Message, ex);
}
}
}
else
{
LogHelper.Info($"入库任务:{areaName}未配置");
}
}
else
{
var areaInfo = Settings.areaInfos.Where(a => a.areaName.Contains(areaName) && a.enable == 1).OrderByDescending(a => a.pri).ToList();
if(areaInfo.Count > 0)
{
foreach(var it in areaInfo)
{
LogHelper.Info($"出库算法01:area:{it.areaName},itemCode:{itemCode}");
var locList = db.Queryable().Where(a => a.S_AREA_CODE == it.areaCode && a.N_CURRENT_NUM > 0).OrderBy(a => a.N_ROW).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).Includes(a => a.LocCntrRel).ToList();
if (locList.Count > 0)
{
if(areaName == "瓶坯即产满框缓存" && string.IsNullOrEmpty(itemCode))
{
locList = locList.Where(a => a.N_ROW == 3).ToList();
}
LogHelper.Info($"出库算法02:查询到可出货位数量:{locList.Count}");
foreach (var a in locList)
{
LogHelper.Info($"出库算法03:查询货位:{a.S_CODE},锁状态:{a.S_LOCK_STATE}");
if (a.S_LOCK_STATE == "无")
{
var cntrInfo = db.Queryable().Where(b => b.S_LOC_CODE == a.S_CODE).First();
if (cntrInfo != null)
{
LogHelper.Info($"出库算法04:当前货位绑定的托盘码为:{cntrInfo.S_CNTR_CODE}");
string endItemCode = "";
var itemInfo = db.Queryable().Where(b => b.S_CNTR_CODE == cntrInfo.S_CNTR_CODE).First();
if (itemInfo != null)
{
endItemCode = itemInfo.S_ITEM_CODE;
}
if (endItemCode == itemCode)
{
//判断当前排有无锁
var lockInfo = db.Queryable().Where(b => b.S_AREA_CODE == it.areaCode && b.N_ROW == a.N_ROW && (b.S_LOCK_STATE == "入库锁" || b.S_LOCK_STATE == "出库锁")).First();
if (lockInfo == null)
{
result = a;
break;
}
else
{
LogHelper.Info($"出库算法05:当前排有锁,货位号:{lockInfo.S_CODE}");
}
}
}
}
}
}
if(result != null)
{
break;
}
}
}
else
{
LogHelper.Info($"出库算法01:{areaName}未配置");
}
}
return result;
}
internal static Location getMStartLoc(SqlSugarClient db, string usingNow)
{
Location result = null;
if(usingNow == "Y")
{
//即产即用
var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产空框" && a.enable == 1).FirstOrDefault();
if (areaInfo != null)
{
var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM > 0 && a.S_LOCK_STATE == "无").Includes(a => a.LocCntrRel).First();
if (locInfo != null)
{
result = locInfo;
}
}
else
{
LogHelper.Info("瓶坯即产空框未配置");
}
}
else
{
//非即产即用
var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯非即产空框" && a.enable == 1).FirstOrDefault();
if (areaInfo != null)
{
var locList = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM > 0).OrderBy(a => a.N_ROW).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).Includes(a => a.LocCntrRel).ToList();
if(locList.Count > 0)
{
foreach(var a in locList)
{
int row = a.N_ROW;
var lockInfo = db.Queryable().Where(b => b.S_AREA_CODE == areaInfo.areaCode && b.N_ROW == row && b.S_LOCK_STATE.Contains("锁")).First();
if(lockInfo == null)
{
result = a;
break;
}
}
}
}
else
{
LogHelper.Info("瓶坯非即产空框未配置");
}
}
return result;
}
///
/// 瓶坯注塑满托下线
///
///
///
///
///
internal static Location BCPFullOut(SqlSugarClient db, string taskName, string itemCode)
{
Location result = null;
LogHelper.Info($"瓶坯注塑满托下线:类型:{taskName},物料编码:{itemCode}");
if (taskName.Contains("即产"))
{
//注塑机即产即用下线,首先下线到即产即用满框线边,满眶线边满了,下到即产即用满框缓存区,满框缓存区满了,下到入库接驳堆叠位
var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产满框" && a.enable == 1).FirstOrDefault();
if(areaInfo != null)
{
var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM < a.N_CAPACITY && a.S_LOCK_STATE == "无").OrderBy(a => a.N_ROW).First();
if(locInfo != null)
{
result = locInfo;
}
}
else
{
LogHelper.Info($"瓶坯注塑满托下线:瓶坯即产满框 未配置");
}
if (result == null)
{
result = TaskProcess.BCPInOrOut(db, true, "瓶坯即产满框缓存", itemCode);
}
if(result == null)
{
result = getJBLoc(db, result);
}
}
else
{
result = getJBLoc(db, result);
}
return result;
}
private static Location getJBLoc(SqlSugarClient db, Location result)
{
//注塑机非即产即用下线,下到入库接驳堆叠位
var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯入库接驳" && a.enable == 1).FirstOrDefault();
if (areaInfo != null)
{
var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM < a.N_CAPACITY && a.S_LOCK_STATE == "无").OrderBy(a => a.N_COL).First();
if (locInfo != null)
{
result = locInfo;
}
else
{
LogHelper.Info("瓶坯注塑满托下线:瓶坯入库接驳位暂时未查询到可用货位");
}
}
else
{
LogHelper.Info($"瓶坯注塑满托下线:瓶坯入库接驳 未配置");
}
return result;
}
///
/// 翻斗机空托下线
///
///
///
///
///
internal static Location BCPEmptyOut(SqlSugarClient db, string taskName)
{
Location result = null;
string endAreaName = taskName.Contains("瓶盖") ? "瓶盖非即产空框" : taskName.Contains("库存") ? "瓶坯非即产空框" : "瓶坯即产空框";
var areaInfo = Settings.areaInfos.Where(a => a.areaName == endAreaName && a.enable == 1).FirstOrDefault();
if (areaInfo != null)
{
var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM < a.N_CAPACITY && a.S_LOCK_STATE == "无").OrderBy(a => a.N_ROW).First();
if (locInfo != null)
{
result = locInfo;
}
}
else
{
LogHelper.Info($"{endAreaName}未配置");
}
if(result == null)
{
if(endAreaName == "翻斗机库存空托下线(瓶坯)")
{
//瓶坯非即产空托下线 如果非即产空框库区无法入库,则下线到瓶坯即产满框缓存 4 5 排
areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产满框缓存" && a.enable == 1).FirstOrDefault();
if (areaInfo != null)
{
var locList = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && (a.N_ROW == 4 || a.N_ROW == 5) && a.N_CURRENT_NUM == 0).OrderBy(a => a.N_ROW).OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
if (locList.Count > 0)
{
foreach (var a in locList)
{
var rowInfo = db.Queryable().Where(b => b.S_AREA_CODE == a.S_AREA_CODE && b.S_ROW == a.S_ROW && a.S_LOCK_STATE == "无").First();
if (rowInfo != null && a.S_LOCK_STATE == "无")
{
result = a;
break;
}
}
}
}
else
{
LogHelper.Info("瓶坯即产满框缓存未配置");
}
}
if(endAreaName == "翻斗机即产空托下线(瓶坯)")
{
//瓶坯即产空托下线 如果即产空框库区无法入库,则下线到瓶坯即产满框缓存 3 排
areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产满框缓存" && a.enable == 1).FirstOrDefault();
if (areaInfo != null)
{
var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_ROW == 3 && a.N_CURRENT_NUM == 0).OrderBy(a => a.N_COL).First();
if (locInfo != null )
{
var rowInfo = db.Queryable().Where(b => b.S_AREA_CODE == locInfo.S_AREA_CODE && b.S_ROW == locInfo.S_ROW && locInfo.S_LOCK_STATE == "无").First();
if (rowInfo != null && locInfo.S_LOCK_STATE == "无")
{
result = locInfo;
}
}
}
else
{
LogHelper.Info("瓶坯即产满框缓存未配置");
}
if(result == null)
{
BCPEmptyOut(db, "翻斗机库存空托下线(瓶坯)");
}
}
}
return result;
}
///
/// FuLeWebPost
///
/// 发送内容
/// 接口名称
/// 扩展参数
///
public static SimpleResult FuLeWebPost(string param, string postName, string Par1 = "", bool extend = false)
{
string msg = ""; string feedback = "";
SimpleResult result = new SimpleResult();
try
{
string webAPIUrl = "";
var httpVerify = new Settings.httpApiVerify();
if (extend) httpVerify = Settings.httpApiVerifys.Where(a => a.VerifyNo == "2" && a.Project == Settings.ProjectName && a.enable == 1).FirstOrDefault();
else httpVerify = Settings.httpApiVerifys.Where(a => a.VerifyNo == "1" && a.Project == Settings.ProjectName && a.enable == 1).FirstOrDefault();
if (httpVerify != null)
{
//采用接口加密方式进行传输
webAPIUrl = $"{Par1}{postName}";
string TokenMsg = "";
string timestamp = DateTime.Now.ToString("s").Replace("T", " ");
TokenMsg = httpVerify.Extend[0] + "from" + httpVerify.Extend[1] + "timestamp" + timestamp;
LogHelper.Info($"【FuLe Post {postName}】:加密前明文:{TokenMsg}", "ThirdSystemLog");
string TokenMsgEncrypt = CryptoDecryptHelper.GetMd5FromString(TokenMsg);
LogHelper.Info($"【FuLe Post {postName}】:加密后密文:{TokenMsgEncrypt}", "ThirdSystemLog");
feedback = httpHelper.WebPost(webAPIUrl, param, "application/json", TokenMsgEncrypt, timestamp,"", extend);
}
else
{
//标准传输方式传输
webAPIUrl = $"{Par1}{postName}" + "&warehouseId=FLUXWMSDB";
feedback = httpHelper.WebPost(webAPIUrl, param);
}
if (!string.IsNullOrEmpty(feedback))
{
LogHelper.Info(JsonConvert.SerializeObject(feedback));
msg = $"【FuLe Post {postName}】WebUrl={webAPIUrl};param={param} ;return={feedback}";
var req = JsonConvert.DeserializeObject(feedback);
if (req.success)
{
result.success = true;
msg = $"【FuLe Post {postName}】success!;WebUrl={webAPIUrl};param={param};return={feedback}";
}
else
{
if (!string.IsNullOrEmpty(req.errMsg)) msg = $"【FuLe Post {postName}】fail!err={req.errMsg};WebUrl={webAPIUrl} ;param={param};return={feedback}";
else msg = $"【FuLe Post {postName}】fail!err={req.message};WebUrl={webAPIUrl} ;param={param};return={feedback}";
}
}
else
{
string errMsg = "can't find the address";
msg = $"【FuLe Post {postName}】fail!err={errMsg};WebUrl={webAPIUrl} ;param={param}";
}
var db = new SqlHelper().GetInstance();
var RepeatUrl = db.Queryable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).First();
if (result.success)
{
if (RepeatUrl != null) db.Deleteable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).ExecuteCommand();
}
else
{
if (RepeatUrl == null)
{
var RepeatInfo = new HttpRepeatSend()
{
SendMsg = param,
UrlName = postName,
Url = Par1,
SendNum = 5
};
db.Insertable(RepeatInfo).ExecuteCommand();
}
else
{
if (RepeatUrl.SendNum == 1) db.Deleteable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).ExecuteCommand();
else
{
RepeatUrl.SendNum = RepeatUrl.SendNum - 1;
db.Updateable(RepeatUrl).UpdateColumns(a => new { a.SendNum }).ExecuteCommand();
}
}
}
}
catch (Exception ex)
{
msg = $"【FuLe Post {postName}】fail!err={ex.Message}";
}
LogHelper.Info(msg, "ThirdSystemLog");
return result;
}
///
/// 接口状态回报处理
///
public class SimpleResult
{
public bool success { get; set; }
public int errCode { get; set; }
public string errMsg { get; set; } = "";
///
/// 淳安二期-响应数据
///
public Object data { get; set; }
///
/// 淳安二期-响应编码
///
public string code { get; set; }
///
/// 淳安二期-响应信息
///
public string message { get; set; }
///
/// 淳安二期-响应信息类型
///
public string messageType { get; set; }
///
/// 淳安二期-异常
///
public Exception exception { get; set; }
}
///
/// 任务信息接口--获取AGV设备信息数据
///
///
///
///
///
///
///
private static void GeneralInterFaceGetAgvDeviceInfoFunc(WCSTask wmsTask, SqlSugarClient db, ref string equipmentCode, ref string orgCode, ref string orgName, ref string proxyInterfaceCode)
{
if (!string.IsNullOrEmpty(wmsTask.S_EQ_NO))
{
var agvDeviceInfo = db.Queryable().Where(a => a.equipmentNo == wmsTask.S_EQ_NO && a.orgCode == Settings.FactoryCode).First();
if (agvDeviceInfo != null)
{
equipmentCode = agvDeviceInfo.equipmentCode;
orgCode = agvDeviceInfo.orgCode;
orgName = agvDeviceInfo.orgName;
proxyInterfaceCode = agvDeviceInfo.proxyInterfaceCode;
}
}
}
///
/// 任务信息接口--获取托盘数据
///
///
private static void GeneralInterFaceGetTrayCodeFunc(WCSTask wmsTask, SqlSugarClient db, List asnReferenceList, List cntrList)
{
//string SrcNo = wmsTask.S_SRC_NO?.Trim();
//
////根据任务中存放的工单号,获取工单类型--因为淳安 满托下线任务包含 下线 值,因此多判断一步,减少工单表的查询
//if (!string.IsNullOrEmpty(SrcNo) && wmsTask.S_TYPE.Contains("下线"))
//{
// var workInfo = db.Queryable().Where(a => a.S_WorkNo == SrcNo).First();
// if (workInfo != null)
// {
// if (workInfo.S_ORDER_TYPE.Trim() != "无码入库")
// {
//
// if (cntrList.Count > 0)
// {
// cntrList.ForEach(a =>
// {
// if (!string.IsNullOrEmpty(a))
// asnReferenceList.Add(new asnReferenceDModel { asnReferenceD = a });
// });
// }
// }
// }
//}
}
///
/// 任务信息接口--获取物料编码
///
///
private static string GeneralInterFaceGetItemCodeFunc(WCSTask wmsTask, SqlSugarClient db, List cntrList, string itemCode)
{
if (cntrList.Count > 0)
{
//string SrcNo = wmsTask.S_SRC_NO?.Trim();
//// 农夫网管下发的工单,物料获取方式
//if (!string.IsNullOrEmpty(SrcNo) && wmsTask.S_TYPE.Contains("下线"))
//{
// var workInfo = db.Queryable().Where(a => a.S_WorkNo == SrcNo).First();
// if (workInfo != null) itemCode = workInfo.S_ItemCode;
//}
//// 其他的人工建立的工单,物料获取方式
//else
//{
// var cntrItemInfo = db.Queryable().Where(a => a.S_CNTR_CODE == cntrList[0]).First();
// if (cntrItemInfo != null)
// {
// //此处查询 物料表,仅限淳安获取MES物料使用,其他工厂可自行注释;因淳安入库物料是使用 物料名称+物料层数 拼接而成,因此需要 通过物料表转换为 MES 的物料编码
// //var itemInfo = db.Queryable().Where(a => a.S_ITEM_NAME == cntrItemInfo.S_ITEM_CODE).First();
// //if (itemInfo != null) itemCode = itemInfo.S_ITEM_CODE;
// itemCode = cntrItemInfo.S_ITEM_CODE;
// }
//}
}
return itemCode;
}
///
/// 绑定货位容器表
///
///
///
internal static bool BindLocCntr(string loc, string cntr, string itemCode, string batchNo, string deviceName = "", string itemlayer = "",string itemName = "")
{
LogHelper.Info($"绑定货位容器表,loc:{loc},cntr:{cntr}");
bool result = true;
List list = new List(cntr.Split(','));
var db = new SqlHelper().GetInstance();
list.ForEach(it =>
{
if (!string.IsNullOrEmpty(it))
{
string cntrCode = it.Trim();
var Cntr = db.Queryable().Where(a => a.S_LOC_CODE == loc && a.S_CNTR_CODE == cntrCode).First();
if (Cntr == null)
{
var cir = new LocCntrRel { S_LOC_CODE = loc, S_CNTR_CODE = cntrCode, S_SRC = deviceName };
if (db.Insertable(cir).ExecuteCommand() > 0) LogHelper.Info($"货位容器表绑定成功,货位号:{loc},托盘号:{cntrCode}");
if (!string.IsNullOrEmpty(itemCode))
{
BindCntrItem(cntrCode, itemCode, batchNo, itemlayer, itemName);
}
}
}
});
//1.0 查货位容器表
return result;
}
///
/// 绑定容器物料表
///
///
///
///
///
internal static bool BindCntrItem(string trayCode, string itemCode, string batchNo, string itemlayer = "",string itemName = "")
{
LogHelper.Info($"绑定容器物料表,trayCode:{trayCode}");
var res = false;
var db = new SqlHelper().GetInstance();
try
{
db.BeginTran();
var Con = db.Queryable().Where(a => a.S_CODE == trayCode).First();
if (Con == null)
{
int detallCount = 1;
if (db.Insertable(new Container
{
S_CODE = trayCode,
N_TYPE = 1,
N_DETAIL_COUNT = detallCount
}).ExecuteCommand() > 0)
{
LogHelper.Info($"容器表绑定成功,托盘号:{trayCode}");
}
}
else
{
Con.N_DETAIL_COUNT = 1;
db.Updateable(Con).UpdateColumns(a => new { a.N_DETAIL_COUNT }).ExecuteCommand();
}
//db.Updateable(cntr).UpdateColumns(it => new { it.S_DEST }).ExecuteCommand();
//1.将原有容器物料信息删除
//db.Deleteable().Where(it => it.S_CNTR_CODE == cntr.S_CNTR_CODE.Trim()).ExecuteCommand();
//2.插入新的容器物料信息(容器号不变)
var info = db.Queryable().Where(a => a.S_CNTR_CODE.Trim() == trayCode.Trim()).First();
if (info == null)
{
var cir = new CntrItemRel { S_CNTR_CODE = trayCode, S_BATCH_NO = batchNo, S_ITEM_CODE = itemCode, S_ITEM_MODEL = itemlayer,S_ITEM_NAME = itemName };
if (db.Insertable(cir).ExecuteCommand() > 0) LogHelper.Info($"容器物料表绑定成功,托盘号:{trayCode},物料编码:{itemCode},物料层数:{itemlayer},物料名称:{itemName}");
}
db.Ado.CommitTran();
res = true;
}
catch (Exception ex)
{
LogHelper.Info($"ex:{ex}");
db.Ado.RollbackTran();
}
return res;
}
///
/// 标准出入库处理
///
/// 起点点位 或 终点点位
/// 任务类型
/// 托盘编码
/// 库区编码
/// 物料编码
/// 批次号
/// 物料层数
/// 物料托盘类型
/// 动作类型 True-入库 False-出库
///
internal static bool LinZhiPlcTask(string bit, string taskType, string trayCode, string areaCode, string itemCode, string batchNo, string itemLayer, string itemTrayType, string deviceName, bool actionType, string workNo = "")
{
var result = false;
var db = new SqlHelper().GetInstance();
if (actionType)
{
LogHelper.Info($"成品入库算法匹配终点,产线号={deviceName},库区={areaCode},物料编码={itemCode},批次号={batchNo}", "输送线");
//1.任务创建:锁定起点,终点,终点排号-排锁定表(任务完成解锁),
// 任务数据携带-托盘码(便于回报)--两个托盘码存入任务表 WMSTask 的 托盘字段 S_CNTRS
// 物料层数(NDC下发必要参数) --起点层数 N_START_LAYER :默认为1
// --终点层数 N_END_LAYER :获取 货位表-终点货位信息 N_CAPACITY + 1
//2.插入 当前排号、产线号 至 自动移库中间表,等待工单完成即进行 自动移库
var info = db.Queryable().Where(a => a.S_ITEM_CODE == itemCode && a.S_TRAY_TYPE == itemTrayType).First();
if (info != null)
{
var endLocation = GetLocationIn(areaCode, itemCode, batchNo);
if (endLocation != null)
{
var layer = endLocation.N_CURRENT_NUM + 1;
//DaMingShanAnalysisMoveLib model = new DaMingShanAnalysisMoveLib { RowNo = endLocation.N_ROW, Batch = batchNo, DeviceName = deviceName };
//WCSHelper.DaMingShanInsertAnalysisMoveLib(model);
result = LinZhiCreateTransport(areaCode, bit, endLocation.S_CODE, taskType, trayCode, 1, layer, deviceName, endLocation.S_ROW, 1, 1, itemTrayType, workNo, batchNo, itemCode);
}
//else //Console.WriteLine($"MoboxHelperCreateTask: 未找到终点货位");
}
else LogHelper.Info($"物料表未匹配到物料信息,物料编码:{itemCode},托盘类型:{itemTrayType}");
}
else
{
//Location startLocation = null;
//string cntrs = "";
//if (taskType == "栈板上线")
//{
// startLocation = GetLocationOutByRow(areaCode, itemTrayType);
// cntrs = startLocation.LocCntrRel.S_CNTR_CODE;
//}
//else
//{
// startLocation = GetLocationOut(areaCode, itemCode, batchNo, itemLayer);
//}
//if (startLocation != null)
//{
// var startLayer = startLocation.N_LAYER;
// var taskNo = DateTime.Now.Ticks.ToString();
// //临江只需要一个一拿
// //var carryCount = startLocation.N_CURRENT_NUM > 3 ? startLocation.N_CURRENT_NUM - 3 : startLocation.N_CURRENT_NUM;
// //出库要从起点获取托盘
// if (cntrs != "")
// {
// var cntrList = LocationHelper.GetLocCntr(startLocation.S_LOC_CODE);
// //临江一个托盘为 一个 货位当前容量
// if (cntrList.Count == startLocation.N_CURRENT_NUM)
// {
// var trayInfo = cntrList.OrderByDescending(a => a.T_CREATE).Skip(1).ToList();
// trayInfo.ForEach(a =>
// {
// cntrs = cntrs + "," + a.S_CNTR_CODE.Trim();
// });
// LogHelper.Info($"cntr:{cntrs}");
// result = LinJiangCreateTransport(areaCode, startLocation.S_LOC_CODE, bit, taskType, cntrs, startLayer, 1, deviceName, startLocation.N_ROW, 1, 1, itemTrayType);
// }
// else
// {
// Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】");
// LogHelper.Info($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】");
// }
// }
//}
//else LogHelper.Info($"对应成品空托库区未找到合适空托,库区编码:{areaCode},托盘类型:{itemTrayType}");
}
return result;
}
///
/// 创建搬运任务
///
///
///
///
///
///
///
///
///
///
public static bool LinZhiCreateTransport(string areaCode, string start, string end, string taskType, string cntrs, int startLayer, int endLayer, string deviceName, string row, int trayCarryCount = 1, int priority = 1, string trayType = "", string workNo = "", string batch = "", string itemcode = "")
{
var db = new SqlHelper().GetInstance();
var result = false;
var taskNo = DateTime.Now.Ticks.ToString();
//var res = TaskHelper.LinJiangCreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, cntrs, deviceName, trayCarryCount, startLayer, endLayer, trayType, workNo, batch, itemcode);
var res = WMSHelper.CreateOpTask(start, end, "入库", taskType, cntrs, trayType, workNo,itemcode);
if (res)
{
try
{
LogHelper.Info($"{taskType}任务创建成功,起点:{start},终点:{end},托盘号:{cntrs},排号:{row},库区编码:{areaCode}");
result = true;
//任务创建成功,起点货位出库锁定,终点货位入库锁定
LocationHelper.LockLoc(start, 2);
LocationHelper.LockLoc(end, 1);
//排锁定
var Sinfo = db.Queryable().Where(a => a.S_CODE == start).First();
var Einfo = db.Queryable().Where(a => a.S_CODE == end).First();
if (Sinfo != null && Einfo != null)
{
string startRow = string.IsNullOrEmpty(Sinfo.S_ROW) ? "" : Sinfo.S_ROW.Trim();
string sArea = string.IsNullOrEmpty(Sinfo.S_AREA_CODE) ? "" : Sinfo.S_AREA_CODE;
string endRow = string.IsNullOrEmpty(Einfo.S_ROW) ? "" : Einfo.S_ROW.Trim();
string eArea = string.IsNullOrEmpty(Einfo.S_AREA_CODE) ? "" : Einfo.S_AREA_CODE;
LockRow(startRow, endRow, sArea, eArea, taskType, taskNo);
if (taskType == "成品下线")
{
//生产下线任务生成成功,删除设备下线时间数据
db.Deleteable().Where(a => a.DeviceName.Trim() == deviceName).ExecuteCommand();
}
}
}
catch (Exception ex)
{
LogHelper.Error(ex.Message, ex);
}
}
return result;
}
///
/// 任务创建时锁定排
///
///
///
public static void LockRow(string startRow, string endRow, string SArea, string EArea, string taskType, string taskNo)
{
string startRowXB = startRow + "";
string endRowXB = endRow + "";
string SAreaXB = SArea + "";
string EAreaXB = EArea + "";
var db = new SqlHelper().GetInstance();
string LockRow = "";
var Srow = db.Queryable().Where(a => a.S_ROW == startRow && a.S_AREA_CODE == SArea).First();
if (Srow != null && !Srow.S_LOCK_STATE.Trim().Contains("锁"))
{
Srow.S_LOCK_STATE = "出库锁";
db.Updateable(Srow).UpdateColumns(it => new { it.S_LOCK_STATE }).ExecuteCommand();
LogHelper.Info($"任务创建成功:TaskNo:{taskNo}.出库锁定:起点库区:{SArea},起点排:{startRow}", "WMSAlgoRithm");
LockRow = LockRow + Srow.S_ROW.Trim().Replace("-XB", "") + ",";
}
var Erow = db.Queryable().Where(a => a.S_ROW == endRow && a.S_AREA_CODE == EArea).First();
if (Erow != null && !Erow.S_LOCK_STATE.Trim().Contains("锁"))
{
Erow.S_LOCK_STATE = "入库锁";
db.Updateable(Erow).UpdateColumns(it => new { it.S_LOCK_STATE }).ExecuteCommand();
LogHelper.Info($"任务创建成功:TaskNo:{taskNo}.入库锁定:起点库区:{EArea},起点排:{endRow}", "WMSAlgoRithm");
LockRow = LockRow + Erow.S_ROW.Trim().Replace("-XB", "") + ",";
}
if (!string.IsNullOrEmpty(LockRow) && taskType.Contains("移库")) TaskProcess.AreaRowLockState(LockRow);//移库任务 回报富勒库位锁定
}
///
/// 根据库区和物料获取入库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在)
///
///
/// 如果itemCode是空表示空容器
/// 标准搬运数量
///
public static Location GetLocationIn(string area, string itemCode, string itemBatch)
{
//库区货位约定:列号越小越靠里
LogHelper.Info($"入库算法01:area:{area},itemCode:{itemCode},itemBatch:{itemBatch}", "WMSAlgoRithm");
Location result = null;
//itemCode = itemCode + itemLayer;
try
{
var db = new SqlHelper().GetInstance();
//成品入库算法,下线的排优先查询之前下线的排
bool action = queryRow(db, area, itemCode, itemBatch, ref result);
if (result == null)
{
//1.0 获取每一排最大的列
//1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除
var listMaxCol = db.Queryable().Where(a => a.S_AREA_CODE == area).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.S_ROW).ToList();
//1.1 查到所有有容器的排
var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area).Includes(a => a.LocCntrRel).OrderBy(a => a.S_ROW).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
if (list.Count > 0)
{
LogHelper.Info($"入库算法03:查到所有有容器的排.数量:{list.Count}", "WMSAlgoRithm");
for (int i = list.Count - 1; i >= 0; i--)
{
//排除已经锁定的货位 和 放满了且是最大列的货位 N_CAPACITY-货位最大容量
//排除已锁定的排
LogHelper.Info($"入库算法04-{i}:[判断当前排是否允许使用].排号:{list[i].S_ROW.Trim()},列号:{list[i].N_COL}," +
$"货位编码:{list[i].S_CODE.Trim()},货位状态:{list[i].S_LOCK_STATE.Trim()},当前数量:{list[i].N_CURRENT_NUM},最大数量:{list[i].N_CAPACITY}", "WMSAlgoRithm");
var rowInfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.S_ROW == list[i].S_ROW.Trim()).First();
LogHelper.Info($"排号:{list[i].S_ROW},锁状态:{rowInfo.S_LOCK_STATE}");
//判断当前库区当前排是否有货位有锁
var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.S_ROW == list[i].S_ROW && a.S_LOCK_STATE != "无").First();
if (locInfo != null || rowInfo.S_LOCK_STATE.Trim() != "无" || list[i].S_LOCK_STATE.Trim() != "无" || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_CODE == list[i].S_CODE) > 0))
{
LogHelper.Info($"入库算法04-{i}:[排除已经锁定的货位和放满了且是最大列的货位].排号:{list[i].S_ROW},排状态:{rowInfo.S_LOCK_STATE.Trim()},货位当前数量:{list[i].N_CURRENT_NUM}", "WMSAlgoRithm");
list.Remove(list[i]);
}
}
if (list.Count > 0)
{
//1.3 遍历判断物料类型是否相同
for (int i = 0; i < list.Count; i++)
{
//todo 还需要判断锁
#region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空
if (list[i].LocCntrRel != null)
{
LogHelper.Info("入库算法04:根据物料获取可用货位。itemCode=" + itemCode, "WMSAlgoRithm");
queryItemInfo(db, list[i], area, itemCode, itemBatch, ref result);
if (result != null)
{
if (action)
{
//将当前货位排和列插入中间表
CPXXTable table = new CPXXTable
{
S_AREA_CODE = area,
S_ROW = list[i].S_ROW,
S_TASK_TYPE = "成品",
};
db.Insertable(table).ExecuteCommand();
}
break;
}
}
else LogHelper.Info("入库算法05:货位容器物料信息为空", "WMSAlgoRithm");
#endregion
}
}
}
if (result == null)
{
//todo 还需要判断锁
#region 查找所有数量是空的排
LogHelper.Info($"入库算法06:无可用货位,获取空排货位。", "WMSAlgoRithm");
//2.0 简化查询只查每一排第一列
list = db.Queryable().Where(a => a.S_AREA_CODE == area).OrderBy(a => a.N_ROW).OrderBy(a => a.N_COL).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList();
//2.1 选一个空排
if (list.Count > 0)
{
LogHelper.Info($"入库算法06:无可用货位,获取空排货位数量为:{list.Count}。", "WMSAlgoRithm");
for (int i = 0; i < list.Count; i++)
{
LogHelper.Info($"入库算法07:获取空排货位:货位编码:{list[i].S_CODE.Trim()},当前数量:{list[i].N_CURRENT_NUM},排号:{list[i].N_ROW},库区编码:{list[i].S_AREA_CODE.Trim()}", "WMSAlgoRithm");
if (list[i].S_LOCK_STATE.Trim().Contains("无"))
{
//二次校验当前排所有货位都是空的,防止系统数据错乱
string row = list[i].S_ROW.Trim();
string areaCode = list[i].S_AREA_CODE.Trim();
var rowLock = db.Queryable().Where(a => a.S_ROW == row && a.S_LOCK_STATE.Contains("锁")).First();
if (rowLock == null)
{
//var rowSumInfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First();
//if (rowSumInfo.sum == 0)
//{
//三次校验 当前排所对应的另一版位的排为空排
//bool DxEmptyCont = JYThreeDxEmptyFunc(area, db, row);
var locInfo = db.Queryable().Where(a => a.S_ROW == row).Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First();
if (locInfo != null)
{
LogHelper.Info($"{locInfo.sum},row:{row}");
if (locInfo.sum == 0)
{
//空排
result = list[i];
if (action)
{
//将当前货位排和列插入中间表
CPXXTable table = new CPXXTable
{
S_AREA_CODE = area,
S_ROW = list[i].S_ROW,
//S_TASK_TYPE = "成品",
};
db.Insertable(table).ExecuteCommand();
}
break;
}
}
else LogHelper.Info("未找到该排");
}
else LogHelper.Info("排锁已上锁");
}
}
}
else LogHelper.Info($"未获取到空排,库区编码:{area}");
#endregion
}
}
}
catch (Exception ex)
{
Console.WriteLine("GetLocationIn:" + ex.Message + ex.StackTrace);
LogHelper.Error("GetLocationIn:" + ex.Message, ex);
}
return result;
}
private static bool queryRow(SqlSugarClient db, string area, string itemCode, string itemBatch, ref Location result)
{
bool action = false;
LogHelper.Info("成品下线查询优先下线排表");
try
{
//1、查询中间表是否有值,有值,则查询中间表指定排的可用货位,当中间表指定排查不到可用货位的时候,进入算法
//2、若没值,进入算法,查询到可用货位,将可用货位的排记录到中间表
//var cpxxInfo = db.Queryable().Where(a => a.S_TASK_TYPE == "成品").First();
var cpxxInfo = db.Queryable().Where(a => a.S_TASK_TYPE == "成品").First();
if (cpxxInfo != null)
{
LogHelper.Info($"当前库区编码:{cpxxInfo.S_AREA_CODE},排号:{cpxxInfo.S_ROW}");
//查询当前排是否有排锁
var rowInfo = db.Queryable().Where(a => a.S_AREA_CODE == cpxxInfo.S_AREA_CODE && a.S_ROW == cpxxInfo.S_ROW).First();
if (rowInfo != null)
{
LogHelper.Info($"锁状态:{rowInfo.S_LOCK_STATE}");
if (rowInfo.S_LOCK_STATE == "无")
{
LogHelper.Info($"aaa");
//查询当前排是否有货位锁
var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == cpxxInfo.S_AREA_CODE && a.S_ROW == cpxxInfo.S_ROW && a.S_LOCK_STATE != "无").First();
if (locInfo == null)
{
LogHelper.Info($"bbb");
//查询当前排最大排是否为满货位
var locInfo1 = db.Queryable().Where(a => a.S_AREA_CODE == cpxxInfo.S_AREA_CODE && a.S_ROW == cpxxInfo.S_ROW).OrderByDescending(a => a.N_COL).First();
if (locInfo1 != null && locInfo1.N_CURRENT_NUM != locInfo1.N_CAPACITY)
{
LogHelper.Info($"ccc");
//查询当前排最大的可用货位 并判断是否是最大列
var endLoc = db.Queryable().Where(a => a.S_AREA_CODE == cpxxInfo.S_AREA_CODE && a.S_ROW == cpxxInfo.S_ROW && a.N_CURRENT_NUM > 0).OrderByDescending(a => a.N_COL).Includes(a => a.LocCntrRel).First();
if (endLoc != null)
{
LogHelper.Info($"ddd");
queryItemInfo(db, endLoc, area, itemCode, itemBatch, ref result);
if (result == null)
{
LogHelper.Info($"fff");
//清除中间表信息
db.Deleteable().Where(a => a.S_ROW == cpxxInfo.S_ROW).ExecuteCommand();
action = true;
}
else
{
//判断当前货位是否有卸货完成之前的任务
string loc = result.S_CODE;
var taskInfo = db.Queryable().Where(a => a.S_END_LOC == loc && a.S_B_STATE != "完成" && a.S_B_STATE != "取消" && a.S_B_STATE != "卸货完成").First();
LogHelper.Info("是否有当前货位任务:" + JsonConvert.SerializeObject(taskInfo));
if (taskInfo != null) result = null;
}
}
}
else
{
//清除中间表信息
db.Deleteable().Where(a => a.S_ROW == cpxxInfo.S_ROW).ExecuteCommand();
action = true;
}
}
}
else if (rowInfo.S_LOCK_STATE == "锁定")
{
//清除中间表信息
db.Deleteable().Where(a => a.S_ROW == cpxxInfo.S_ROW).ExecuteCommand();
action = true;
LogHelper.Info($"queryRow:该排有锁,库区编码:{cpxxInfo.S_AREA_CODE},排号:{cpxxInfo.S_ROW},锁状态:{rowInfo.S_LOCK_STATE}");
}
else
{
LogHelper.Info($"queryRow:该排有锁,库区编码:{cpxxInfo.S_AREA_CODE},排号:{cpxxInfo.S_ROW},锁状态:{rowInfo.S_LOCK_STATE}");
}
}
else LogHelper.Info($"queryRow:该排未找库区编码:{cpxxInfo.S_AREA_CODE},排号:{cpxxInfo.S_ROW}");
}
else action = true;
}
catch (Exception ex)
{
LogHelper.Error("queryRow:" + ex.Message, ex);
}
return action;
}
private static void queryItemInfo(SqlSugarClient db, Location loc, string area, string itemCode, string itemBatch, ref Location result)
{
string cntrCode = loc.LocCntrRel.S_CNTR_CODE;
var itemInfo = db.Queryable().Where(a => a.S_CNTR_CODE == cntrCode).First();
if ((itemCode != null && itemInfo != null && itemInfo.S_ITEM_CODE.Trim() == itemCode) || (itemCode == null && itemInfo == null))
{
LogHelper.Info("物料编码匹配成功");
LogHelper.Info($"{itemInfo.S_BATCH_NO}");
//相同物料 相同批次
if (itemInfo.S_BATCH_NO.Trim() == itemBatch.Trim())
{
LogHelper.Info("批次号匹配成功");
//当前数量小于当前容量
if (loc.N_CURRENT_NUM < loc.N_CAPACITY)
{
string locCode = loc.S_CODE.Trim();
var trayInfo = db.Queryable().Where(a => a.S_LOC_CODE == locCode).ToList();
if (trayInfo.Count() % 2 == 0)
{
result = loc;
string code11 = result.S_CODE;
var taskINfo = db.Queryable().Where(a => a.S_END_LOC == code11 && a.S_B_STATE == "取货完成").First();
if (taskINfo != null)
{
result = null;
}
LogHelper.Info($"入库算法05:当前货位可用,获取当前货位。当前货位:{loc.S_CODE.Trim()}.", "WMSAlgoRithm");
}
else
{
//1.33 不满足则选择后一列,后一列肯定是空货位
result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == loc.N_ROW && a.N_COL > loc.N_COL).OrderBy(a => a.N_COL).First();
if (result.S_LOCK_STATE != "无") result = null;
LogHelper.Info($"入库算法05:当前货位托盘数量可求余2,获取后一列货位。当前货位:{loc.S_CODE.Trim()},托盘数量:{trayInfo.Count()}.", "WMSAlgoRithm");
}
}
else
{
//当前货位满了,比他col大一位的货位,后一列肯定是空货位
result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == loc.N_ROW && a.N_COL > loc.N_COL).OrderBy(a => a.N_COL).First();
//if (result.S_LOCK_STATE != "无") result = null;
LogHelper.Info($"入库算法05:当前货位已满,获取后一列空位。当前货位:{loc.S_CODE.Trim()}.", "WMSAlgoRithm");
}
}
//相同物料 不同批次号 ,需间隔一个货位 col-1
else
{
result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == loc.N_ROW && a.N_COL - 1 > loc.N_COL).OrderBy(a => a.N_COL).First();
//if (result.S_LOCK_STATE != "无") result = null;
LogHelper.Info($"入库算法05:相同物料 不同批次号 ,需间隔一个货位,当前货位:{loc.S_CODE.Trim()}.", "WMSAlgoRithm");
}
}
}
///
/// 计算瓶坯非即产空托起点
///
///
internal static Location FJCKTLoc()
{
var db = new SqlHelper().GetInstance();
Location result = null;
//在瓶坯即产满框 查询 4 5两排的空框
var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产满框缓存" && a.enable == 1).FirstOrDefault();
if(areaInfo != null)
{
var locList = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && (a.N_ROW == 4 || a.N_ROW == 5) && a.N_CURRENT_NUM > 0).OrderBy(a => a.N_ROW).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
if(locList.Count > 0)
{
foreach (var a in locList)
{
var cntrInfo = db.Queryable().Where(b => b.S_LOC_CODE == a.S_CODE).First();
if(cntrInfo != null)
{
var itemInfo = db.Queryable().Where(b => b.S_CNTR_CODE == cntrInfo.S_CNTR_CODE).First();
if(itemInfo == null)
{
var rowInfo = db.Queryable().Where(b => b.S_AREA_CODE == a.S_AREA_CODE && b.S_ROW == a.S_ROW && b.S_LOCK_STATE == "无").First();
if (rowInfo != null && a.S_LOCK_STATE == "无")
{
result = a;
break;
}
}
}
}
}
}
if(result == null)
{
result = TaskProcess.BCPInOrOut(db, false, "瓶坯库区", "");
}
return result;
}
///
/// 取消任务
///
///
///
internal static void cancelTask(WCSTask TN_Task)
{
if(!WCSHelper.CheckActionRecordExist(TN_Task.S_CODE, 4))
{
//取消任务
WCSHelper.UpdateStatus(TN_Task.S_CODE, 4);
if (TN_Task.S_TYPE == "接驳位入库")
{
new SqlHelper().GetInstance().Deleteable().Where(a => TN_Task.S_CNTR_CODE.Contains(a.S_CNTR_CODE)).ExecuteCommand();
new SqlHelper().GetInstance().Deleteable().Where(a => TN_Task.S_CNTR_CODE.Contains(a.S_CNTR_CODE)).ExecuteCommand();
}
}
else
{
WCSHelper.UpdateStatus(TN_Task.S_CODE, 3);
}
var op = WMSHelper.GetWmsTask(TN_Task.S_OP_CODE);
if (op != null)
{
//等待直接修改状态为取消
op.N_B_STATE = 2;
WMSHelper.UpdateTaskState(op);
}
NDCApi.CancelOrder(TN_Task.S_CODE.Trim());
OperateStatus(TN_Task, 7);
}
}
}