using HH.WCS.Mobox3.HD.core;
|
using HH.WCS.Mobox3.HD.models;
|
using HH.WCS.Mobox3.HD.util;
|
using HH.WCS.Mobox3.HD.wms;
|
using Newtonsoft.Json;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using static HH.WCS.Mobox3.HD.api.ApiModel;
|
using static HH.WCS.Mobox3.HD.api.MoboxController;
|
using static HH.WCS.Mobox3.HD.api.OtherModel;
|
using static HH.WCS.Mobox3.HD.api.WmsController;
|
using static HH.WCS.Mobox3.HD.util.Settings;
|
using static HH.WCS.Mobox3.HD.wms.WMSHelper;
|
|
namespace HH.WCS.Mobox3.HD.api {
|
/// <summary>
|
/// api接口辅助类
|
/// </summary>
|
public class ApiHelper {
|
static ApiHelper() {
|
|
}
|
/// <summary>
|
/// 创建任务
|
/// </summary>
|
/// <param name="model"></param>
|
internal static void AddTask(AddTaskModel model) {
|
if (!WCSHelper.CheckExist(model.No)) {
|
if (LocationHelper.CheckExist(model.From) && LocationHelper.CheckExist(model.To)) {
|
WCSHelper.CreateTask(model.No, model.From, model.To, "搬运", 99, "");
|
}
|
|
}
|
}
|
/// <summary>
|
/// 创建入库单主子表
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
internal static SimpleResult Putaway_Order_In(Putaway_Order_In model) {
|
var result = new SimpleResult();
|
//创建入库单主子表
|
var po = WMSHelper.GetPutawayOrder(model.Data.arrival_no);
|
if (po == null) {
|
po = new PutawayOrder { S_NO = model.Data.arrival_no, S_BS_TYPE = model.Data.op_type };
|
po.Details = new List<PutawayDetail>();
|
if (model.Data.items.Count > 0) {
|
model.Data.items.ForEach(a => {
|
po.Details.Add(new PutawayDetail
|
{
|
S_PUTAWAY_NO = model.Data.arrival_no,
|
N_ROW_NO = po.Details.Count + 1,
|
S_ITEM_CODE = a.item_code,
|
F_QTY = a.qty,
|
S_BATCH_NO = a.batch_no,
|
});
|
});
|
WMSHelper.CreatePutawayOrder(po);
|
}
|
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// 创建发货单主子表
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
internal static SimpleResult OutboundOrder(OutboundOrder model) {
|
var result = new SimpleResult();
|
//创建发货单,人工点确认后生成分拣单,没有缺货的自动更新为失败,有货的更新为执行中
|
//创建出库单主子表
|
var po = WMSHelper.GetShippingOrder(model.Data.out_no);
|
if (po == null) {
|
po = new ShippingOrder { S_NO = model.Data.out_no, S_BS_TYPE = model.Data.op_type };
|
po.Details = new List<ShippingDetail>();
|
if (model.Data.items.Count > 0) {
|
model.Data.items.ForEach(a => {
|
po.Details.Add(new ShippingDetail
|
{
|
S_SHIPPING_NO = model.Data.out_no,
|
N_ROW_NO = po.Details.Count + 1,
|
S_ITEM_CODE = a.item_code,
|
F_QTY = a.qty,
|
S_BATCH_NO = a.batch_no,
|
});
|
});
|
WMSHelper.CreateShippingOrder(po);
|
}
|
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// pad入库
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
internal static SimpleResult Instock(InstockInfo model) {
|
var result = new SimpleResult();
|
//pda入库
|
//1 判断起点有没有任务,有没有入库锁
|
var loc = LocationHelper.GetLoc(model.start);
|
if (loc != null && loc.N_LOCK_STATE == 0) {
|
//2 根据终点库区计算终点
|
var end = WMSHelper.GetInstockEnd(model.item, model.endArea);
|
if (end != null) {
|
var cntrCode = ContainerHelper.GenerateCntrNo();
|
var wcsTask = new WCSTask
|
{
|
S_OP_NAME = "入库",
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_TYPE = "下线入库",
|
S_START_LOC = model.start,
|
S_END_LOC = end.S_CODE,
|
S_SCHEDULE_TYPE = "NDC",
|
N_CNTR_COUNT = 1,
|
S_CNTR_CODE = cntrCode,
|
N_START_LAYER = 1,
|
N_END_LAYER = end.N_CURRENT_NUM + 1
|
};
|
if (ContainerHelper.BindNewCntrItem(model.start, cntrCode, model.item) && WCSHelper.CreateTask(wcsTask)) {
|
LocationHelper.LockLoc(model.start, 2);
|
LocationHelper.LockLoc(end.S_CODE, 1);
|
result.resultCode = 0;
|
result.resultMsg = $"任务创建成功,任务号为{wcsTask.S_CODE},终点为{end.S_CODE}";
|
}
|
}
|
else {
|
result.resultCode = 2;
|
result.resultMsg = "未获取到入库终点";
|
}
|
}
|
else {
|
result.resultCode = 1;
|
result.resultMsg = "起点有任务未完成";
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// 移库
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
internal static SimpleResult shiftStock(ShiftStockInfo model)
|
{
|
var result = new SimpleResult();
|
//1 根据起点库区、排 确定起始货位
|
var startLoc = WMSHelper.GetShiftStockStart(model.item, model.startArea, model.startRow);
|
if (startLoc != null && startLoc.N_LOCK_STATE == 0)
|
{
|
//2 根据终点库区计算终点
|
var end = WMSHelper.GetShiftStockEnd(model.item, model.endArea, model.startRow);
|
if (end != null && end.N_LOCK_STATE == 0)
|
{
|
var wcsTask = new WCSTask
|
{
|
S_OP_NAME = "移库",
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_TYPE = "移库",
|
S_START_LOC = startLoc.S_CODE,
|
S_END_LOC = end.S_CODE,
|
S_SCHEDULE_TYPE = "NDC",
|
N_CNTR_COUNT = 1,
|
S_CNTR_CODE = startLoc.LocCntrRel.S_CNTR_CODE,
|
N_START_LAYER = startLoc.N_CURRENT_NUM,
|
N_END_LAYER = end.N_CURRENT_NUM + 1
|
};
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
LocationHelper.LockLoc(startLoc.S_CODE, 2);
|
LocationHelper.LockLoc(end.S_CODE, 1);
|
result.resultCode = 0;
|
result.resultMsg = $"任务创建成功,任务号为{wcsTask.S_CODE},终点为{end.S_CODE}";
|
}
|
}
|
else
|
{
|
result.resultCode = 2;
|
result.resultMsg = "未获取到移库终点";
|
}
|
}
|
else
|
{
|
result.resultCode = 1;
|
result.resultMsg = "未获取到移库起点";
|
}
|
return result;
|
}
|
|
|
internal static CodeInfo GetCodeInfo(string code, string org) {
|
//return new CodeInfo { Fitemid_XK=code, FSourceNo="123456"};
|
CodeInfo result = null;
|
try {
|
var db = new SqlHelper<object>().GetInstance(Settings.SqlServer1);
|
var nameP = new SugarParameter("@FBarCode", code);
|
var orgP = new SugarParameter("@Forg", org);
|
//var ageP = new SugarParameter("@age", null, true);//设置为output
|
//var dt = db.Ado.UseStoredProcedure().GetDataTable("sp_school", nameP, ageP);//返回dt
|
result = db.Ado.UseStoredProcedure().SqlQuery<CodeInfo>("WMS_FBarCode", nameP, orgP).First();//返回List
|
Console.WriteLine($"读存储过程成功,result={result}");
|
}
|
catch (Exception ex) {
|
Console.WriteLine(ex.Message);
|
}
|
return result;
|
}
|
// ---------------------------------- 哈电 -------------------------------------
|
|
private static readonly object in_lock = new object();
|
|
/// <summary>
|
/// 入库请求参数验证
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static ResponseResult inStockRequestParamVerify(InStockInfo model) {
|
ResponseResult responseResult = new ResponseResult() { success = false };
|
if (model.taskType.Equals("半成品/成品入库") && (model.trayItemInfoList == null || model.trayItemInfoList.Count == 0))
|
{
|
responseResult.message = "物料信息不能为空!";
|
return responseResult;
|
}
|
LocCntrRel locCntrRel = ContainerHelper.getLocCntr(model.trayCode);
|
if (locCntrRel != null && !locCntrRel.S_LOC_CODE.Equals(model.startBit))
|
{
|
responseResult.message = $"起点货位与容器货位不匹配,当前起点货位:{model.startBit},系统显示容器应该所在货位:{locCntrRel.S_LOC_CODE}";
|
return responseResult;
|
}
|
var existWmsTask = WMSHelper.GetWmsTaskByCntr(model.trayCode);
|
if (existWmsTask != null)
|
{
|
responseResult.message = $"相关容器存在未完成任务【已有{existWmsTask.T_CREATE.ToString("yyyy-MM-dd HH:mm:ss")}的{existWmsTask.S_TYPE}任务】";
|
return responseResult;
|
}
|
return null;
|
}
|
|
internal static int freqFlag = 0;
|
|
/// <summary>
|
/// 按一定频率分配库区(频率 1栋立库:7栋立库:横栋立库 = 1:2:1)
|
/// </summary>
|
/// <returns></returns>
|
public static Dictionary<int, string> distributeArea() {
|
Dictionary<int, string> map = new Dictionary<int, string>();
|
List<StoreAreaInfo> areaInfos = Settings.storeAreaInfos.Where(a => a.cargoType == 1).ToList();
|
int index = 0;
|
foreach (var item in areaInfos)
|
{
|
for (int i = 0; i < item.frequency; i++)
|
{
|
map.Add(index, item.areaCode);
|
index++;
|
}
|
}
|
return map;
|
}
|
|
/// <summary>
|
/// 查询半成品/成品入库任务终点
|
/// </summary>
|
/// <param name="model"></param>
|
public static TaskEndData getInStcokTaskEnd(InStockInfo model) {
|
TaskEndData taskEndData = new TaskEndData();
|
List<string> conLocCodes = new List<string>();
|
Location endLoc = null;
|
Location firstTaskEnd = null;
|
var map = distributeArea(); //按规定频率分配库区
|
string areaCode = Settings.getStoreAreaByAccessArea(model.endArea);
|
// 优先选定库区入库
|
if (areaCode != null)
|
{
|
LogHelper.Info("车间任务号:" + JsonConvert.SerializeObject(model.taskNo), "Mobox");
|
conLocCodes = LocationHelper.GetConnectLocation(areaCode, 1, 1, 1, model.startArea);
|
if (conLocCodes != null && conLocCodes.Count > 0)
|
{
|
foreach (var item in conLocCodes)
|
{
|
LogHelper.Info("接驳位:" + JsonConvert.SerializeObject(item), "Mobox");
|
var conLoc = LocationHelper.GetLoc(item);
|
endLoc = WMSHelper.GetEndLocation(areaCode, model.trayItemInfoList[0].itemCode, conLoc.N_ROADWAY, conLoc.N_ROW);
|
if (endLoc != null)
|
{
|
firstTaskEnd = conLoc;
|
endLoc.S_CODE = "虚拟货位";
|
break;
|
}
|
}
|
}
|
}
|
// 如选定库区不能入库,则选择其他库区
|
/*if (endLoc == null)
|
{
|
// TODO freqFlag = 1
|
freqFlag = 1;
|
if (map.TryGetValue(freqFlag, out areaCode))
|
{
|
conLocCodes = LocationHelper.GetConnectLocation(areaCode, 1, freqFlag == 2 ? 2 : 1, 1, model.startArea);
|
if (conLocCodes != null && conLocCodes.Count > 0)
|
{
|
foreach (var item in conLocCodes)
|
{
|
var conLoc = LocationHelper.GetLoc(item);
|
endLoc = WMSHelper.GetEndLocation(areaCode, model.trayItemInfoList[0].itemCode, conLoc.N_ROADWAY, conLoc.N_ROW);
|
if (endLoc != null)
|
{
|
firstTaskEnd = conLoc;
|
|
freqFlag += 1;
|
if (freqFlag == 4)
|
{
|
freqFlag = 0;
|
}
|
break;
|
}
|
}
|
}
|
}
|
}*/
|
|
if (endLoc != null)
|
{
|
// 绑定容器物料信息
|
model.trayItemInfoList.ForEach(it =>
|
{
|
CntrItemRel cntrItemRel = new CntrItemRel()
|
{
|
S_ITEM_CODE = it.itemCode,
|
S_ITEM_NAME = it.itemName,
|
S_WORK_NO = it.workNo,
|
S_WORK_NAME = it.workName,
|
S_DEPART_NO = it.dePartNo,
|
S_PART_TASK_ID = it.partTaskId,
|
S_PARTDRAW_NO = it.partDrawNo,
|
S_PART_NAME = it.partName,
|
S_OPER_NO = it.operNo,
|
S_OPER_NAME = it.operName,
|
F_QTY = float.Parse(it.quantity == null ? "0" : it.quantity),
|
F_WEIGHT = float.Parse(it.weight == null ? "0" : it.weight),
|
S_ITEM_SPEC = it.spec,
|
S_ITEM_TYPE = it.isFinish
|
};
|
ContainerHelper.initContainer(model.trayCode);
|
ContainerHelper.BindCntrItemSingle(model.trayCode, cntrItemRel);
|
});
|
}
|
taskEndData.endLoc = endLoc;
|
taskEndData.firstTaskEnd = firstTaskEnd;
|
return taskEndData;
|
}
|
|
/// <summary>
|
/// 查询钢卷入库任务终点
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static TaskEndData steelCoilInStock(InStockInfo model) {
|
TaskEndData taskEndData = new TaskEndData();
|
List<string> conLocCodes = new List<string>();
|
Location endLoc = null;
|
Location firstTaskEnd = null;
|
var coil = ItemHelper.GetCoilItemInfo(model.trayCode);
|
if (coil != null)
|
{
|
coil.S_WORK_NAME = model.trayItemInfoList[0].workName;
|
ItemHelper.UpdateCntrItemInfo(coil);
|
ContainerHelper.addCntr(model.trayCode);
|
}
|
else
|
{
|
return null;
|
}
|
endLoc = new Location() { S_CODE = "虚拟库位", S_AREA_CODE = "虚拟库区" };
|
List<string> gjkAreaCodes = Settings.getStoreAreaCodes(1, 2);
|
foreach (var gjArea in gjkAreaCodes)
|
{
|
var connectLoc = LocationHelper.GetConnectLocation(gjArea, 1).FirstOrDefault();
|
if (connectLoc != null)
|
{
|
firstTaskEnd = LocationHelper.GetLoc(connectLoc);
|
break;
|
}
|
}
|
taskEndData.endLoc = endLoc;
|
taskEndData.firstTaskEnd = firstTaskEnd;
|
return taskEndData;
|
}
|
|
/// <summary>
|
/// 查询空盘垛入库终点
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static TaskEndData emptyTrayInStock(InStockInfo model) {
|
TaskEndData taskEndData = new TaskEndData();
|
List<string> conLocCodes = new List<string>();
|
Location endLoc = null;
|
Location firstTaskEnd = null;
|
var map = distributeArea(); //按规定频率分配库区
|
string areaCode = Settings.getStoreAreaByAccessArea(model.endArea);
|
|
if (freqFlag == 4 || freqFlag % 4 == 3)
|
{
|
freqFlag = 0;
|
}
|
if (map.TryGetValue(freqFlag, out areaCode))
|
{
|
conLocCodes = LocationHelper.GetConnectLocation(areaCode, 1, 1, 1);
|
foreach (var item in conLocCodes)
|
{
|
var conLoc = LocationHelper.GetLoc(item);
|
endLoc = WMSHelper.GetEndLocation(areaCode, null, conLoc.N_ROADWAY, conLoc.N_ROW);
|
if (endLoc != null)
|
{
|
firstTaskEnd = conLoc;
|
endLoc.S_CODE = "虚拟货位";
|
break;
|
}
|
}
|
}
|
freqFlag += 1;
|
|
taskEndData.endLoc = endLoc;
|
taskEndData.firstTaskEnd = firstTaskEnd;
|
return taskEndData;
|
}
|
|
/// <summary>
|
/// 查询模具入库终点
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static TaskEndData mouldInStock(InStockInfo model) {
|
TaskEndData taskEndData = new TaskEndData();
|
Location endLoc = null;
|
Location firstTaskEnd = null;
|
|
MouldCntr mouldCntr = MouldHelper.GetMouldCntr(new MouldCntr() { S_CNTR_CODE = model.trayCode });
|
if (mouldCntr != null)
|
{
|
ContainerHelper.addCntr(model.trayCode);
|
endLoc = LocationHelper.GetLocation(mouldCntr.S_LOC_CODE);
|
firstTaskEnd = endLoc;
|
}
|
|
taskEndData.endLoc = endLoc;
|
taskEndData.firstTaskEnd = firstTaskEnd;
|
return taskEndData;
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static TaskEndData finishInStockTemporaryArea(InStockInfo model) {
|
TaskEndData taskEndData = new TaskEndData();
|
Location endLoc = null;
|
Location firstTaskEnd = null;
|
|
if (model.endArea != null)
|
{
|
endLoc = WMSHelper.GetDeliverEndLocation(model.endArea);
|
}
|
|
if (endLoc == null)
|
{
|
List<string> areaCodes = Settings.getDispatchAreaCodes();
|
foreach (var item in areaCodes)
|
{
|
endLoc = WMSHelper.GetDeliverEndLocation(item);
|
if (endLoc != null)
|
{
|
break;
|
}
|
}
|
}
|
|
firstTaskEnd = endLoc;
|
if (endLoc != null)
|
{
|
// 绑定容器物料信息
|
model.trayItemInfoList.ForEach(it =>
|
{
|
CntrItemRel cntrItemRel = new CntrItemRel()
|
{
|
S_ITEM_CODE = it.itemCode,
|
S_ITEM_NAME = it.itemName,
|
S_WORK_NO = it.workNo,
|
S_WORK_NAME = it.workName,
|
S_DEPART_NO = it.dePartNo,
|
S_PARTDRAW_NO = it.partDrawNo,
|
S_PART_NAME = it.partName,
|
S_OPER_NO = it.operNo,
|
S_OPER_NAME = it.operName,
|
F_QTY = float.Parse(it.quantity == null ? "0" : it.quantity),
|
F_WEIGHT = float.Parse(it.weight == null ? "0" : it.weight),
|
S_ITEM_SPEC = it.spec,
|
S_ITEM_TYPE = it.isFinish
|
};
|
ContainerHelper.BindCntrItemSingle(model.trayCode, cntrItemRel);
|
});
|
}
|
|
taskEndData.endLoc = endLoc;
|
taskEndData.firstTaskEnd = firstTaskEnd;
|
return taskEndData;
|
}
|
|
public class TaskEndData {
|
public Location endLoc { get; set; }
|
public Location firstTaskEnd { get; set; }
|
}
|
|
|
/// <summary>
|
/// 创建入库搬运任务
|
/// * 钢卷\模具入库需要传起点库位
|
/// * 任务类型分为 半成品/成品入库 、钢卷入库 、模具入库、模具托盘回库
|
/// * 半成品/成品入库 横栋、1栋、7栋的分配频率为 1:1:2
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
internal static ResponseResult createInOrder(InStockInfo model)
|
{
|
ResponseResult responseResult = new ResponseResult() { success = true };
|
InStockRetureData retureData = new InStockRetureData(){ startStationCode = model.startBit,startAreaCode = model.startArea };
|
|
var response = inStockRequestParamVerify(model); // 参数验证
|
if (response != null) {
|
return response;
|
}
|
|
var map = distributeArea(); //按规定频率分配库区
|
|
|
Location startLoc = LocationHelper.GetLoc(model.startBit);
|
Location endLoc = null;
|
Location firstTaskEnd = null; // 一阶段任务终点
|
TaskEndData taskEndData = null;
|
List<string> conLocCodes = new List<string>();
|
lock (in_lock) {
|
switch (model.taskType)
|
{
|
case "半成品/成品入库":
|
taskEndData = getInStcokTaskEnd(model);
|
if (taskEndData.firstTaskEnd == null)
|
{
|
responseResult.success = false;
|
responseResult.message = "当前区域无可用接驳位,请排查";
|
return responseResult;
|
}
|
break;
|
case "钢卷入库":
|
taskEndData = steelCoilInStock(model);
|
break;
|
case "模具入库":
|
case "模具托盘入库":
|
taskEndData = mouldInStock(model);
|
break;
|
case "空盘垛入库":
|
taskEndData = emptyTrayInStock(model);
|
break;
|
case "成品入库备货区":
|
taskEndData = finishInStockTemporaryArea(model);
|
break;
|
default:
|
responseResult.success = false;
|
responseResult.message = "没有相应的任务类型";
|
return responseResult;
|
}
|
}
|
|
if (startLoc == null)
|
{
|
if (model.taskType.Contains("模具") || model.taskType.Contains("钢卷"))
|
{
|
responseResult.success = false;
|
responseResult.message = "开始货位未指定或不存在";
|
return responseResult;
|
}
|
startLoc = new Location() { S_CODE = model.startBit, S_AREA_CODE = model.startArea };
|
}
|
else
|
{
|
if (startLoc.N_LOCK_STATE != 0)
|
{
|
responseResult.success = false;
|
responseResult.message = "开始货位已上锁";
|
return responseResult;
|
}
|
}
|
|
if (taskEndData != null)
|
{
|
endLoc = taskEndData.endLoc;
|
firstTaskEnd = taskEndData.firstTaskEnd;
|
}
|
|
// 2.创建入库作业任务
|
if (endLoc != null )
|
{
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = model.trayCode,
|
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 = model.taskType,
|
S_OP_DEF_CODE = model.taskNo,
|
S_OP_DEF_NAME = "入库搬运任务",
|
N_PRIORITY = model.taskPri == null ? 1 : int.Parse(model.taskPri),
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
string S_SCHEDULE_TYPE = "HL";
|
if (model.taskType.Equals("半成品/成品入库") || model.taskType.Equals("空盘垛入库") || model.taskType.Equals("成品入库备货区"))
|
{
|
S_SCHEDULE_TYPE = "LD-AUTO";
|
}
|
|
// 创建一段入库任务
|
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 + "-1",
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = firstTaskEnd.S_CODE,
|
S_END_AREA = firstTaskEnd.S_AREA_CODE,
|
S_SCHEDULE_TYPE = S_SCHEDULE_TYPE,
|
N_PRIORITY = 1,
|
T_START_TIME = DateTime.Now,
|
};
|
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 起点、接驳点、终点加锁
|
LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
|
LocationHelper.LockLoc(firstTaskEnd.S_CODE, 1);
|
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
}
|
retureData.wmsId = wmsTask.S_CODE;
|
retureData.endStationCode = firstTaskEnd.S_CODE;
|
retureData.endAreaCode = firstTaskEnd.S_AREA_CODE;
|
responseResult.result = retureData;
|
}
|
}
|
else
|
{
|
responseResult.success = false;
|
responseResult.message = "未获取到终点库位";
|
}
|
return responseResult;
|
}
|
|
private static readonly object out_lock = new object();
|
|
/// <summary>
|
/// 移库(立库出库阻塞)
|
/// </summary>
|
/// <param name="outLoc"></param>
|
/// <param name="wmsTaskId"></param>
|
/// <returns></returns>
|
public static bool shiftStock(Location outLoc,string wmsTaskId) {
|
bool result = false;
|
string outCntrCode = ContainerHelper.getLocCntrByLoc(outLoc.S_CODE).S_CNTR_CODE;
|
var cntrItemRels = ItemHelper.GetCntrItemByCntrCode(outCntrCode);
|
string itemCode = null;
|
if(cntrItemRels != null && cntrItemRels.Count > 0)
|
{
|
itemCode = cntrItemRels[0].S_ITEM_CODE;
|
}
|
Location inLoc = WMSHelper.GetEndLocation(outLoc.S_AREA_CODE, itemCode, outLoc.N_ROADWAY, 1);
|
|
// 进行移库操作
|
if (inLoc != null)
|
{
|
var shiftWcsTask = new WCSTask
|
{
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_TYPE = "移库",
|
S_START_LOC = outLoc.S_CODE,
|
S_START_AREA = outLoc.S_AREA_CODE,
|
S_END_LOC = inLoc.S_CODE,
|
S_END_AREA = inLoc.S_AREA_CODE,
|
S_CNTR_CODE = outCntrCode,
|
S_SCHEDULE_TYPE = "RB",
|
S_OP_CODE = wmsTaskId,
|
S_EQ_NO = getEqNo(outLoc.S_AREA_CODE, outLoc.N_ROADWAY),
|
N_PRIORITY = 9,
|
T_START_TIME = DateTime.Now,
|
};
|
if (WCSHelper.CreateTask(shiftWcsTask))
|
{
|
LocationHelper.LockLoc(outLoc.S_CODE, 2);
|
LocationHelper.LockLoc(inLoc.S_CODE, 1);
|
result = true;
|
}
|
}
|
return result;
|
}
|
|
|
/// <summary>
|
/// 创建出库搬运任务
|
/// *钢卷/模具出库需要指定终点
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
internal static ResponseResult createOutOrder(OutStockInfo model) {
|
ResponseResult responseResult = new ResponseResult(){success = false};
|
|
Location endLoc = LocationHelper.GetLoc(model.endBit);
|
if (endLoc == null)
|
{
|
if (model.taskType.Contains("模具") || model.taskType.Contains("钢卷"))
|
{
|
responseResult.message = "终点货位未指定或不存在";
|
return responseResult;
|
}
|
endLoc = new Location() { S_CODE = model.endBit, S_AREA_CODE = model.endArea };
|
}
|
else
|
{
|
if (endLoc.N_LOCK_STATE != 0)
|
{
|
responseResult.message = "终点货位已上锁";
|
return responseResult;
|
}
|
}
|
|
Location startLoc = null;
|
Location firstTaskEnd = null;
|
ItemStartLoc itemStartLoc = new ItemStartLoc();
|
MouldCntr mouldCntr = null;
|
// 1、查询开始货位、终点货位
|
lock (out_lock)
|
{
|
switch (model.taskType)
|
{
|
case "半成品/成品出库":
|
itemStartLoc = WMSHelper.GetStartLocation(model.itemCode, model.partTaskId, model.workNo, null, model.endArea);
|
if (itemStartLoc.type != 0)
|
{
|
startLoc = itemStartLoc.loc;
|
firstTaskEnd = itemStartLoc.connectloc;
|
if (startLoc != null && firstTaskEnd == null) {
|
responseResult.message = "堆垛机或输送线设备可能存在故障,请排查";
|
return responseResult;
|
}
|
}
|
else
|
{
|
responseResult.message = "库区没有该物料";
|
return responseResult;
|
}
|
break;
|
case "钢卷出库":
|
startLoc = WMSHelper.GetGJStartLocation(model.itemCode, model.coilNo, model.workNo, model.weight, model.width);
|
break;
|
case "模具出库":
|
var mouldCntrs = MouldHelper.GetMouldCntrList(new MouldCntr() { S_ITEM_CODE = model.itemCode, S_MOULD_NO = model.itemCode });
|
if (mouldCntrs != null && mouldCntrs.Count > 0)
|
{
|
mouldCntr = mouldCntrs[0];
|
startLoc = LocationHelper.GetLocation(mouldCntr.S_LOC_CODE);
|
if (startLoc.N_LOCK_STATE != 0 || startLoc.N_CURRENT_NUM == 0)
|
{
|
responseResult.message = "模具库位已出库或已上锁";
|
return responseResult;
|
}
|
}
|
break;
|
case "模具托盘出库":
|
mouldCntr = MouldHelper.GetMouldCntr(new MouldCntr() { S_ITEM_CODE = model.itemCode, S_MOULD_NO = model.itemCode });
|
if (mouldCntr != null)
|
{
|
startLoc = LocationHelper.GetLocation(mouldCntr.S_LOC_CODE);
|
if (startLoc.N_LOCK_STATE != 0 || startLoc.N_CURRENT_NUM == 0)
|
{
|
responseResult.message = "模具托盘已出库或已上锁";
|
return responseResult;
|
}
|
}
|
break;
|
case "叫托盘出库":
|
if (model.trayCode != null)
|
{
|
itemStartLoc = WMSHelper.GetStartLocationByTrayCode(model.trayCode, model.endArea);
|
if (itemStartLoc.type != 0)
|
{
|
startLoc = itemStartLoc.loc;
|
firstTaskEnd = itemStartLoc.connectloc;
|
}
|
else
|
{
|
responseResult.message = "该托盘处于不可用状态:锁定、禁用、阻塞、不存在";
|
return responseResult;
|
}
|
}
|
else
|
{
|
responseResult.message = "托盘号不能为空";
|
return responseResult;
|
}
|
break;
|
case "空盘垛出库":
|
itemStartLoc = WMSHelper.GetStartLocation(null, null, null, null,model.endArea);
|
if (itemStartLoc.type != 0)
|
{
|
startLoc = itemStartLoc.loc;
|
firstTaskEnd = itemStartLoc.connectloc;
|
}
|
else
|
{
|
responseResult.message = "库区没有该物料";
|
return responseResult;
|
}
|
break;
|
}
|
|
if (startLoc == null){
|
responseResult.message = "未找到符合出库条件的物料";
|
return responseResult;
|
}
|
|
// 2、创建出库作业任务
|
string cntrCode = null;
|
LocCntrRel locCntrRel = ContainerHelper.getLocCntrByLoc(startLoc.S_CODE);
|
if (locCntrRel != null){
|
cntrCode = locCntrRel.S_CNTR_CODE;
|
}
|
|
var existWmsTask = WMSHelper.GetWmsTaskByCntr(cntrCode);
|
if (existWmsTask != null){
|
responseResult.message = "相关容器存在未完成任务";
|
return responseResult;
|
}
|
|
Location externalTaskStartLoc = null;
|
// 模具钢卷出库只有一段任务
|
if (model.taskType.Contains("模具") || model.taskType.Contains("钢卷"))
|
{
|
externalTaskStartLoc = startLoc;
|
firstTaskEnd = endLoc;
|
}
|
else
|
{
|
if (firstTaskEnd != null) {
|
externalTaskStartLoc = LocationHelper.GetLoc(WCSHelper.GetLinePlcInfoByLoc(firstTaskEnd.S_CODE).descLocation);
|
}
|
}
|
|
WMSTask wmsTask = null;
|
if (firstTaskEnd != null)
|
{
|
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 = model.taskType,
|
S_OP_DEF_CODE = model.taskNo,
|
S_OP_DEF_NAME = "出库搬运任务",
|
N_PRIORITY = int.Parse(model.taskPri),
|
T_START_TIME = DateTime.Now};
|
|
LogHelper.Info($"开始创建作业任务,创建时间:" + DateTime.Now, "车间控制器");
|
|
if (WMSHelper.CreateWmsTask(wmsTask)){
|
|
LogHelper.Info($"创建作业任务完成,创建时间:" + DateTime.Now, "车间控制器");
|
// 物料不可取货位,需先进行移库
|
if ((model.taskType.Equals("半成品/成品出库") || model.taskType.Equals("空盘垛出库") || model.taskType.Equals("叫托盘出库")) && itemStartLoc.type == 2){
|
bool shiftResult = shiftStock(itemStartLoc.outLoc,wmsTask.S_CODE);
|
if (!shiftResult) {
|
wmsTask.N_B_STATE = 3;
|
WMSHelper.UpdateTaskState(wmsTask);
|
|
responseResult.message = "取货阻塞且巷道两边货物已满,无法取货";
|
return responseResult;
|
}
|
}
|
|
// 查询立体库库区
|
string S_SCHEDULE_TYPE = null;
|
List<string> areaCodes = Settings.getStoreAreaCodes(2, 1);
|
if (areaCodes.Contains(startLoc.S_AREA_CODE)){
|
S_SCHEDULE_TYPE = "RB";
|
/* string firstEndLoc = WCSHelper.GetLinePlcInfoByDesc(firstTaskEnd.S_CODE).localtion;
|
firstTaskEnd = LocationHelper.GetLoc(firstEndLoc);*/
|
}
|
else{
|
S_SCHEDULE_TYPE = "HL";
|
}
|
|
var wcsTask = new WCSTask{
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
S_TYPE = wmsTask.S_TYPE + "-1",
|
S_START_LOC = startLoc.S_CODE,
|
S_START_AREA = startLoc.S_AREA_CODE,
|
S_END_LOC = firstTaskEnd.S_CODE,
|
S_END_AREA = firstTaskEnd.S_AREA_CODE,
|
S_CNTR_CODE = cntrCode,
|
S_SCHEDULE_TYPE = S_SCHEDULE_TYPE,
|
S_OP_CODE = wmsTask.S_CODE,
|
S_EQ_NO = getEqNo(startLoc.S_AREA_CODE, startLoc.N_ROADWAY),
|
N_PRIORITY = 1,
|
T_START_TIME = DateTime.Now};
|
|
LogHelper.Info($"开始创建任务,创建时间:" + DateTime.Now, "车间控制器");
|
|
if (WCSHelper.CreateTask(wcsTask)){
|
|
LogHelper.Info($"创建任务完成,创建时间:" + DateTime.Now, "车间控制器");
|
// 开始货位、终点货位进行加锁
|
LocationHelper.LockLoc(startLoc.S_CODE, 2);
|
LocationHelper.LockLoc(firstTaskEnd.S_CODE, 1);
|
LocationHelper.LockLoc(endLoc.S_CODE, 1);
|
// 更新作业任务状态
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
}
|
}
|
}
|
else{
|
responseResult.message = "接驳位处于锁定状态,请联系管理人员解锁";
|
return responseResult;
|
}
|
// 3、组装返回数据
|
return assembleResponseData(externalTaskStartLoc, endLoc, model.taskType, wmsTask);
|
}
|
}
|
|
/// <summary>
|
/// 组装返回数据
|
/// </summary>
|
/// <param name="externalTaskStartLoc"></param>
|
/// <param name="endLoc"></param>
|
/// <param name="taskType"></param>
|
/// <param name="wmsTask"></param>
|
/// <returns></returns>
|
public static ResponseResult assembleResponseData(Location externalTaskStartLoc,Location endLoc ,string taskType ,WMSTask wmsTask ) {
|
ResponseResult responseResult = new ResponseResult() { success = true };
|
OutStockReturnData outStockReturnData = new OutStockReturnData()
|
{
|
startStationCode = externalTaskStartLoc.S_CODE,
|
startAreaCode = externalTaskStartLoc.S_AREA_CODE,
|
endStationCode = endLoc.S_CODE,
|
endAreaCode = endLoc.S_AREA_CODE,
|
wmsId = wmsTask.S_CODE
|
};
|
List<TrayItemInfoRes> trayItemInfos = new List<TrayItemInfoRes>();
|
|
if ("模具出库".Equals(taskType) || "模具托盘出库".Equals(taskType))
|
{
|
MouldCntr mouldCntr = MouldHelper.GetMouldCntr(new MouldCntr() { S_CNTR_CODE = wmsTask.S_CNTR_CODE });
|
foreach (var item in mouldCntr.mouldDetails)
|
{
|
TrayItemInfoRes trayItemInfo = new TrayItemInfoRes()
|
{
|
trayCode = mouldCntr.S_CNTR_CODE,
|
itemCode = item.S_MOULD_NO,
|
itemName = item.S_NAME,
|
quantity = item.N_QTY.ToString()
|
};
|
trayItemInfos.Add(trayItemInfo);
|
}
|
}
|
else
|
{
|
List<CntrItemRel> cntrItemRels = ContainerHelper.GetCntrItemRel(wmsTask.S_CNTR_CODE);
|
foreach (var item in cntrItemRels)
|
{
|
TrayItemInfoRes trayItemInfo = new TrayItemInfoRes()
|
{
|
trayCode = item.S_CNTR_CODE,
|
workNo = item.S_WORK_NO,
|
dePartNo = item.S_DEPART_NO,
|
partTaskId = item.S_PART_TASK_ID,
|
partDrawNo = item.S_PARTDRAW_NO,
|
partName = item.S_PART_NAME,
|
operNo = item.S_OPER_NO,
|
operName = item.S_OPER_NAME,
|
itemCode = item.S_ITEM_CODE,
|
itemName = item.S_ITEM_NAME,
|
spec = item.S_ITEM_SPEC,
|
quantity = item.F_QTY.ToString(),
|
weight = item.F_WEIGHT.ToString(),
|
width = item.S_WIDTH,
|
isFinish = item.S_ITEM_TYPE,
|
};
|
trayItemInfos.Add(trayItemInfo);
|
}
|
}
|
outStockReturnData.trayItemInfo = trayItemInfos;
|
responseResult.result = outStockReturnData;
|
return responseResult;
|
}
|
|
/// <summary>
|
/// 获取堆垛机设备号
|
/// </summary>
|
/// <param name="areaCode"></param>
|
/// <param name="roadWay"></param>
|
/// <returns></returns>
|
public static string getEqNo(string areaCode,int roadWay) {
|
DevicePlcInfo devicePlcInfo = Settings.devicePlcInfos.Where(a => a.area == areaCode && a.roadway == roadWay).FirstOrDefault();
|
if (devicePlcInfo != null) {
|
return devicePlcInfo.deviceNo;
|
}
|
return null;
|
}
|
|
/// <summary>
|
/// 钢卷入库
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
public static SimpleResult steelCoilIntoStorage(SteelCoilInStockInfo model) {
|
SimpleResult result = new SimpleResult();
|
var startLoc = LocationHelper.GetLoc(model.locCode);
|
if (startLoc == null ) {
|
result.resultCode = 1;
|
result.resultMsg = "开始货位不存在";
|
return result;
|
}
|
var mst = WMSHelper.GetWmsTaskByCntr(model.coilNo);
|
if (mst != null)
|
{
|
result.resultCode = 1;
|
result.resultMsg = "该钢卷存在执行中的任务";
|
return result;
|
}
|
var coil = ItemHelper.GetCoilItemInfo(model.coilNo);
|
if (coil != null)
|
{
|
var gjWeight = WCSCore.getGjWeight(model.locCode, model.coilNo);
|
if (gjWeight == 0) {
|
result.resultCode = 1;
|
result.resultMsg = "钢卷重量为0";
|
return result;
|
}
|
|
Location endLoc = WMSHelper.GetGJEndLocation(gjWeight);
|
|
if ( endLoc != null)
|
{
|
var wmsTask = new WMSTask()
|
{
|
S_CNTR_CODE = model.coilNo,
|
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 = 1,
|
};
|
|
if (WMSHelper.CreateWmsTask(wmsTask))
|
{
|
var wcsTask = new WCSTask
|
{
|
S_OP_CODE = wmsTask.S_CODE,
|
S_OP_NAME = wmsTask.S_OP_DEF_NAME,
|
S_CODE = WCSHelper.GenerateTaskNo(),
|
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_CNTR_CODE = model.coilNo,
|
S_SCHEDULE_TYPE = "HL",
|
};
|
if (WCSHelper.CreateTask(wcsTask))
|
{
|
// 开始货位、终点货位进行加锁
|
LocationHelper.LockLoc(startLoc.S_CODE, 2);
|
LocationHelper.LockLoc(endLoc.S_CODE, 1);
|
|
wmsTask.N_B_STATE = 1;
|
WMSHelper.UpdateTaskState(wmsTask);
|
}
|
}
|
}
|
else {
|
result.resultCode = 1;
|
result.resultMsg = "没有可入的钢卷货位";
|
}
|
}
|
else
|
{
|
result.resultCode = 1;
|
result.resultMsg = "未查询到钢卷信息";
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// 初始化模具
|
/// </summary>
|
/// <param name="model"></param>
|
public static void initMould(mouldModel model) {
|
var oldMouldCntr = MouldHelper.GetMouldCntrByCntr(model.trayCode);
|
if (oldMouldCntr != null)
|
{
|
MouldHelper.deleteMouldByCntr(model.trayCode);
|
}
|
|
MouldCntr mouldCntr = new MouldCntr()
|
{
|
S_ITEM_CODE = model.itemCode,
|
S_CNTR_CODE = model.trayCode,
|
S_MOULD_NO = model.mouldNo,
|
S_MOULD_TYPE = model.mouldType,
|
S_LOC_CODE = model.locCode,
|
S_ABLE_FLAG = model.ableFlag
|
};
|
MouldHelper.addMould(mouldCntr);
|
ContainerHelper.addCntr(mouldCntr.S_CNTR_CODE);
|
|
List<MouldDetail> mouldDetails = new List<MouldDetail>();
|
|
MouldDetail aMouldDetail = new MouldDetail()
|
{
|
S_MOULD_NO = model.mouldNo,
|
S_NAME = "主片模块",
|
N_INIT_QTY = model.aMouldNum,
|
N_QTY = model.aMouldNum,
|
};
|
mouldDetails.Add(aMouldDetail);
|
|
MouldDetail bMouldDetail = new MouldDetail()
|
{
|
S_MOULD_NO = model.mouldNo,
|
S_NAME = "项号片模块",
|
N_INIT_QTY = model.bMouldNum,
|
N_QTY = model.bMouldNum,
|
};
|
mouldDetails.Add(bMouldDetail);
|
|
MouldDetail cMouldDetail = new MouldDetail()
|
{
|
S_MOULD_NO = model.mouldNo,
|
S_NAME = "冲头",
|
N_INIT_QTY = model.cMouldNum,
|
N_QTY = model.cMouldNum,
|
};
|
mouldDetails.Add(cMouldDetail);
|
|
MouldHelper.batchAddChildMould(mouldDetails);
|
}
|
|
/// <summary>
|
/// 初始化模具
|
/// </summary>
|
/// <param name="mouldNo"></param>
|
/// <param name="aMouldNum">主片模块</param>
|
/// <param name="bMouldNum">项号片模块</param>
|
/// <param name="cMouldNum">冲头</param>
|
public static void updateMouldNum(string mouldNo , int aMouldNum ,int bMouldNum ,int cMouldNum)
|
{
|
List<MouldDetail> mouldDetails = MouldHelper.GetMouldDetails(mouldNo);
|
if (mouldDetails != null && mouldDetails.Count > 0) {
|
foreach (var detail in mouldDetails)
|
{
|
if (detail.S_NAME == "主片模块")
|
{
|
detail.N_QTY = aMouldNum;
|
}
|
if (detail.S_NAME == "项号片模块")
|
{
|
detail.N_QTY = bMouldNum;
|
}
|
if (detail.S_NAME == "冲头")
|
{
|
detail.N_QTY = cMouldNum;
|
}
|
}
|
MouldHelper.updateMouldNum(mouldDetails);
|
}
|
}
|
|
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; }
|
}
|
}
|
}
|