.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/18c7ba82-96c0-49b8-853d-f97228ef5b2e.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/1e814f61-56d2-4923-b635-2c4903d5fcef.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/3c46e31b-92c1-46e5-92fd-f14f17b3bb37.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/62511dbf-e9d3-41f0-9ebd-1f1dfea56ad8.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/62c30b9e-0d60-4b2a-b4d8-3f249467cf7b.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/6f070d61-bbc8-4cf3-8d70-7244f5a6b3b6.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/a8b2e367-f0d3-4c52-a750-33ba036c1ad8.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/adcc1e79-4e50-42ee-ad7b-9a8e583b3401.vsidxBinary files differ
api/ApiHelper.cs
@@ -18,6 +18,9 @@ /// <summary> /// 好运箱-满箱下线入库(PDA) /// </summary> /// <remarks> /// 流程:人工将满箱从产线搬运到操作区后,使用PDA调用接口,呼叫AGV将满箱搬运到货架区(不指定终点货区) /// </remarks> /// <param name="model">包含:物料信息、起点货位</param> /// <returns></returns> public static SimpleResult GoodpackOffline(GoodpackOfflineInfo model) { @@ -34,8 +37,8 @@ var cgDetail = db.Queryable<TN_CG_Detail>() .Where(d => d.S_ITEM_CODE == model.ItemCode && d.S_BATCH_NO == model.BatchNo) // 指定:物料编码、批次号 .Where(d => d.N_ITEM_STATE == 1 && d.S_ITEM_STATE == "待检") // 新增物料,故物料状态应该为 1待检 // TODO model 中 数量、规格是否也参与比对 待后续要求 .First(); .First(); // TODO model 中 数量、规格是否也参与比对 待后续要求 // 如果找不到指定的物料,说明信息不一致,报错 if (cgDetail == null) { info = $"PDA扫码物料信息与贴标机传递的信息不一致:" + JsonConvert.SerializeObject(model); @@ -44,6 +47,7 @@ } // 查询起点货位,是否符合要求(初次下线要求货位无容器) // 注:起点货位绑定前没有货物,数量为 0 var startLoc = db.Queryable<TN_Location>() .Where(l => l.S_CODE == model.StartLoc) // 指定:起点货位号 .Where(l => l.N_LOCK_STATE == 0 && l.S_LOCK_STATE == "无" && l.C_ENABLE == "Y") // 筛选:未上锁 @@ -57,12 +61,29 @@ return NewSimpleResult(3, info); } startLoc.N_CURRENT_NUM = 1; // 绑定后,修改起点货位数量为 1 // 绑定货位和容器号(满箱下线到操作区,此时尚未绑定) var locCntrRel = new TN_Loc_Container { S_LOC_CODE = model.StartLoc, S_CNTR_CODE = cgDetail.S_CNTR_CODE, S_CNTR_TYPE = "好运箱", }; // 每个新插入容器的逻辑,都需要查询这个表是否存在,如果不存在也加入,如果存在:暂不更新结果(待定) // 更详细的,是空箱入库,和满料下线这两个流程的容器可能是新的,其余容器一定是旧的,无需再判断 // 严格来说,容器类型应该放在Container里面的,Loc_Container表只放关系,不过暂时先这样改吧 var cntrItemRel = db.Queryable<TN_Container_ItemType>() .Where(c => c.S_CNTR_CODE == locCntrRel.S_CNTR_CODE).First(); var insertContainerItemType = false; if (cntrItemRel == null) { insertContainerItemType = true; cntrItemRel = new TN_Container_ItemType { S_ITEM_CODE = cgDetail.S_ITEM_CODE, // 物料类型对于好运箱而言其实不用,主要是类型 S_CNTR_TYPE = locCntrRel.S_CNTR_TYPE, S_CNTR_CODE = locCntrRel.S_CNTR_CODE, }; } // TODO 满箱入库算法待优化 var endLoc = db.Queryable<TN_Location>() @@ -78,6 +99,7 @@ return NewSimpleResult(4, info); } // 数据库操作部分 var cntId = locCntrRel.S_CNTR_CODE; var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName); @@ -85,6 +107,15 @@ LocationHelper.LockEndLoc(ref endLoc); // 终点入库锁 using (var tran = db.Ado.UseTran()) { if (insertContainerItemType) { if (db.Insertable<TN_Container_ItemType>(cntrItemRel).ExecuteCommand() <= 0) { info = $"插入容器信息失败:" + JsonConvert.SerializeObject(cntrItemRel); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (db.Insertable<TN_Loc_Container>(locCntrRel).ExecuteCommand() <= 0) { info = $"插入货位容器关系失败:" + JsonConvert.SerializeObject(locCntrRel); tran.RollbackTran(); @@ -96,7 +127,8 @@ it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY it.T_MODIFY, it.N_CURRENT_NUM, // 起点货位绑定后,将货位状态更新 }).ExecuteCommand() <= 0) { tran.RollbackTran(); info = $"生成任务'{taskName}'失败:更新起点货位{startLoc.S_CODE}锁状态失败"; @@ -139,6 +171,10 @@ /// <summary> /// 托盘-空托入库(PDA) /// </summary> /// <remarks> /// 人工将空托盘通过接驳位入库,需要新绑定容器货位<br/> /// 由于空托盘一般是出库卸货后获得,而出库时没有手动卸货的逻辑,所以需要在入库的时候再删除旧绑定信息 /// </remarks> /// <param name="model"></param> /// <returns></returns> public static SimpleResult EmptyInboundPallet(EmptyInboundInfo model) { @@ -164,28 +200,49 @@ return NewSimpleResult(2, info); } //// 查看容器是否已有物料绑定 //var cgDetail = db.Queryable<TN_CG_Detail>() // .Where(d => d.S_CNTR_CODE == model.CntrCode).First(); //// 如果有绑定物料,报错,因为空托不应该有物料 //if (cgDetail != null) { // info = $"容器{model.CntrCode}已经绑定了物料{cgDetail.S_ITEM_CODE},不是空托无法入库"; // LogHelper.Info(info); // return NewSimpleResult(3, info); //} // 假定人工不会将有物料的箱子放在空箱入库接驳位,没有必要检查 // 如果人工将出库后的托盘入库,这时物料信息并没有删除,需要将托盘物料的关系解除 var cgDetail = db.Queryable<TN_CG_Detail>() var cgDetailOld = db.Queryable<TN_CG_Detail>() .Where(d => d.S_CNTR_CODE == model.CntrCode).First(); var needDeleteDetail = cgDetail != null; // 绑定货位和容器号(PDA在接驳位绑定 // 如果人工将出库后的托盘入库,此时容器仍然与旧的出库货位绑定,需要检查 var locCntrRelOld = db.Queryable<TN_Loc_Container>() .Where(c => c.S_CNTR_CODE == model.CntrCode).First(); //var locOld = new TN_Location(); TN_Location locOld = null; if (locCntrRelOld != null) { // 如果需要解绑容器货位,也需要修改货位信息 locOld = db.Queryable<TN_Location>() .Where(l => l.S_CODE == locCntrRelOld.S_LOC_CODE).First(); if (locOld != null) { locOld.N_CURRENT_NUM = 0; // 如果旧货位存在,将旧货位的数量设置为 0 } } //else { // locOld = null; //} // 绑定货位和容器号(PDA在接驳位绑定) var locCntrRel = new TN_Loc_Container { S_LOC_CODE = model.StartLoc, S_CNTR_CODE = model.CntrCode, S_CNTR_TYPE = "托盘", }; // 每个新插入容器的逻辑,都需要查询这个表是否存在,如果不存在也加入,如果存在:暂不更新结果(待定) // 更详细的,是空箱入库,和满料下线这两个流程的容器可能是新的,其余容器一定是旧的,无需再判断 // 严格来说,容器类型应该放在Container里面的,Loc_Container表只放关系,不过暂时先这样改吧 var cntrItemRel = db.Queryable<TN_Container_ItemType>() .Where(c => c.S_CNTR_CODE == locCntrRel.S_CNTR_CODE).First(); var insertContainerItemType = false; if (cntrItemRel == null) { insertContainerItemType = true; cntrItemRel = new TN_Container_ItemType { S_ITEM_CODE = "", // 空托盘刚入库,没有物料类型,就默认先为空 S_CNTR_TYPE = locCntrRel.S_CNTR_TYPE, S_CNTR_CODE = locCntrRel.S_CNTR_CODE, }; } // TODO 暂定选择最低层按区位顺序入库,后面待修改 var endLoc = db.Queryable<TN_Location>() @@ -208,13 +265,49 @@ LocationHelper.LockEndLoc(ref endLoc); // 终点入库锁 using (var tran = db.Ado.UseTran()) { if (insertContainerItemType) { if (db.Insertable<TN_Container_ItemType>(cntrItemRel).ExecuteCommand() <= 0) { info = $"插入容器信息失败:" + JsonConvert.SerializeObject(cntrItemRel); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (cgDetailOld != null) { if (db.Deleteable<TN_CG_Detail>(cgDetailOld).ExecuteCommand() <= 0) { info = $"删除旧物料信息失败:" + JsonConvert.SerializeObject(cgDetailOld); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (locCntrRelOld != null) { if (db.Deleteable<TN_Loc_Container>(locCntrRelOld).ExecuteCommand() <= 0) { info = $"删除旧货位容器关系失败:" + JsonConvert.SerializeObject(locCntrRelOld); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (locOld != null) { if (db.Updateable<TN_Location>(locOld).UpdateColumns(l => l.N_CURRENT_NUM).ExecuteCommand() <= 0) { info = $"更新旧货位容器数量失败:" + JsonConvert.SerializeObject(locOld); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (db.Insertable<TN_Loc_Container>(locCntrRel).ExecuteCommand() <= 0) { info = $"插入货位容器关系失败:" + JsonConvert.SerializeObject(locCntrRel); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, @@ -262,6 +355,10 @@ /// <summary> /// 好运箱-空箱入库(PDA) /// </summary> /// <remarks> /// 人工将空箱通过接驳位入库,需要新绑定容器货位<br/> /// 由于空箱一般是出库卸货后获得,而出库时没有手动卸货的逻辑,所以需要在入库的时候再删除旧绑定信息 /// </remarks> /// <returns></returns> public static SimpleResult EmptyInboundGoodpack(EmptyInboundInfo model) { var db = new SqlHelper<object>().GetInstance(); @@ -285,15 +382,27 @@ return NewSimpleResult(2, info); } // 查看容器是否已有物料绑定 var cgDetail = db.Queryable<TN_CG_Detail>() // 假定人工不会将有物料的箱子放在空箱入库接驳位,没有必要检查 // 如果人工将出库后的托盘入库,这时物料信息并没有删除,需要将托盘物料的关系解除 var cgDetailOld = db.Queryable<TN_CG_Detail>() .Where(d => d.S_CNTR_CODE == model.CntrCode).First(); // 如果有绑定物料,报错,因为空箱不应该有物料 if (cgDetail != null) { info = $"容器{model.CntrCode}已经绑定了物料{cgDetail.S_ITEM_CODE},不是空箱无法入库"; LogHelper.Info(info); return NewSimpleResult(3, info); // 如果人工将出库后的托盘入库,此时容器仍然与旧的出库货位绑定,需要检查 var locCntrRelOld = db.Queryable<TN_Loc_Container>() .Where(c => c.S_CNTR_CODE == model.CntrCode).First(); //var locOld = new TN_Location(); TN_Location locOld = null; if (locCntrRelOld != null) { // 如果需要解绑容器货位,也需要修改货位信息 locOld = db.Queryable<TN_Location>() .Where(l => l.S_CODE == locCntrRelOld.S_LOC_CODE).First(); if (locOld != null) { locOld.N_CURRENT_NUM = 0; // 如果旧货位存在,将旧货位的数量设置为 0 } } //else { // locOld = null; //} // 绑定货位和容器号 var locCntrRel = new TN_Loc_Container { @@ -301,6 +410,21 @@ S_CNTR_CODE = model.CntrCode, S_CNTR_TYPE = "好运箱", }; // 每个新插入容器的逻辑,都需要查询这个表是否存在,如果不存在也加入,如果存在:暂不更新结果(待定) // 更详细的,是空箱入库,和满料下线这两个流程的容器可能是新的,其余容器一定是旧的,无需再判断 // 严格来说,容器类型应该放在Container里面的,Loc_Container表只放关系,不过暂时先这样改吧 var cntrItemRel = db.Queryable<TN_Container_ItemType>() .Where(c => c.S_CNTR_CODE == locCntrRel.S_CNTR_CODE).First(); var insertContainerItemType = false; if (cntrItemRel == null) { insertContainerItemType = true; cntrItemRel = new TN_Container_ItemType { S_ITEM_CODE = "", // 空托盘刚入库,没有物料类型,就默认先为空 S_CNTR_TYPE = locCntrRel.S_CNTR_TYPE, S_CNTR_CODE = locCntrRel.S_CNTR_CODE, }; } // TODO 暂定选择最低层顺序入库,后面待修改 var endLoc = db.Queryable<TN_Location>() @@ -323,6 +447,42 @@ LocationHelper.LockEndLoc(ref endLoc); // 终点入库锁 using (var tran = db.Ado.UseTran()) { if (insertContainerItemType) { if (db.Insertable<TN_Container_ItemType>(cntrItemRel).ExecuteCommand() <= 0) { info = $"插入容器信息失败:" + JsonConvert.SerializeObject(cntrItemRel); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (cgDetailOld != null) { if (db.Deleteable<TN_CG_Detail>(cgDetailOld).ExecuteCommand() <= 0) { info = $"删除旧物料信息失败:" + JsonConvert.SerializeObject(cgDetailOld); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (locCntrRelOld != null) { if (db.Deleteable<TN_Loc_Container>(locCntrRelOld).ExecuteCommand() <= 0) { info = $"删除旧货位容器关系失败:" + JsonConvert.SerializeObject(locCntrRelOld); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (locOld != null) { if (db.Updateable<TN_Location>(locOld).UpdateColumns(l => l.N_CURRENT_NUM).ExecuteCommand() <= 0) { info = $"更新旧货位容器数量失败:" + JsonConvert.SerializeObject(locOld); tran.RollbackTran(); LogHelper.Info(info); return NewSimpleResult(5, info); } } if (db.Insertable<TN_Loc_Container>(locCntrRel).ExecuteCommand() <= 0) { info = $"插入货位容器关系失败:" + JsonConvert.SerializeObject(locCntrRel); tran.RollbackTran(); @@ -377,6 +537,9 @@ /// <summary> /// 托盘-空托上线(PDA) /// </summary> /// <remarks> /// 人工根据当前生产物料所需的容器类型,呼叫AGV从空容器货架中叫一个符合要求的托盘 /// </remarks> /// <param name="model"></param> /// <returns></returns> public static SimpleResult EmptyOnlinePallet(EmptyOnlinePalletInfo model) { @@ -693,6 +856,12 @@ return NewSimpleResult(1, info); } } /// <summary> /// 抽检-不合格移库(PDA) /// </summary> /// <param name="model"></param> /// <returns></returns> public static SimpleResult UnqualifiedShift(UnqualifiedShiftInfo model) { var db = new SqlHelper<object>().GetInstance(); var info = ""; @@ -811,6 +980,11 @@ } } /// <summary> /// 余料回库/尾箱回库(PDA) /// </summary> /// <param name="model"></param> /// <returns></returns> public static SimpleResult RestBack(RestBackInfo model) { var db = new SqlHelper<object>().GetInstance(); var info = ""; @@ -824,17 +998,24 @@ .Where(l => l.N_CURRENT_NUM == 1) .First(); if (startLoc == null) { info = $"没有找到起点货位{model.StartLoc},或不具备取货要求:未上锁、有货物"; LogHelper.Info(info); return NewSimpleResult(2, info); } var locCntrRel = db.Queryable<TN_Loc_Container>() .Where(c => c.S_LOC_CODE == model.StartLoc) .First(); if (locCntrRel == null) { info = $"没有找到起点货位{model.StartLoc},或不具备取货要求:未上锁、有货物"; info = $"没有找到起点货位{model.StartLoc}所绑定的容器"; LogHelper.Info(info); return NewSimpleResult(3, info); } var endLoc = new TN_Location(); //var endLoc = new TN_Location(); TN_Location endLoc = null; if (locCntrRel.S_CNTR_TYPE == "托盘") { endLoc = db.Queryable<TN_Location>() .Where(l => Settings.AreaMap[AreaName.M满托货架区].Contains(l.S_AREA_CODE)) @@ -849,15 +1030,16 @@ .Where(l => l.N_CURRENT_NUM == 0) // 起点绑定前没有容器 .First(); } else { endLoc = null; } //else { // endLoc = null; //} if (endLoc == null) { info = "查询:没有找到合适的终点货位"; LogHelper.Info(info); return NewSimpleResult(3, info); } var cntId = locCntrRel.S_CNTR_CODE; var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName); @@ -911,7 +1093,7 @@ } /// <summary> /// 成品胶出库(PDA) /// 成品胶出库(PDA) 待定,暂时不需要此功能 /// </summary> /// <remarks> /// WMS提供出库的物料类型与数量,调用接口由WCS生成具体的出库任务,然后WCS后台轮询处理 @@ -1130,32 +1312,38 @@ } /// <summary> /// 博实物料信息下发同步 /// 博实物料信息下发同步(只针对好运箱) /// </summary> /// <param name="model"></param> /// <returns></returns> public static MesResult CgInfoSync(CgInfoSyncInfo model) { var db = new SqlHelper<object>().GetInstance(); var random = new Random(); var info = ""; try { // 将下发的信息先存储到CG表中(此时托盘没有与产线处的货位绑定) var detail = new TN_CG_Detail { S_ITEM_CODE = model.ItemCode, S_ITEM_NAME = model.ItemName, S_CNTR_CODE = GenerateOrderNo("容器号", "CN"), // NOTE 容器号:目前随机(后期可能会指定,或者PDA绑定时再填入) S_CNTR_CODE = model.CntrCode, // 料箱编号(待定,现在暂时设定为博实下发) S_BATCH_NO = model.BatchNo, S_STANDARD = model.Standard, S_NET_WEIGHT = model.NetWeight, S_QUALITY_GRADE = model.QualityGrade, //N_PRODUCT_LINE = random.Next(0, 3), // NOTE 产线号:目前随机(后期可能会指定,或者PDA绑定时再填入) }; //var locCntrRel = new TN_Loc_Container { // //S_LOC_CODE = Settings.Config.ProductionLines[detail.N_PRODUCT_LINE].OffLoc[0], // 好运箱的位置是操作区,不是产线 // S_CNTR_CODE = detail.S_CNTR_CODE, // S_CNTR_TYPE = "好运箱", // 贴标机只针对好运箱 //}; // 产线号的逻辑待定,现在设定为博实下发产线号,看后续需求变更 // 好运箱起点为产线货位,人工将好运箱从产线上取下,搬运到满好运箱操作区 //var startLocCode = ""; //if (model.ProdLineId.Trim() == "3") { // startLocCode = ""; //} //if (model.ProdLineId.Trim() != "3" || model.ProdLineId.Trim() != "4") { // info = $"不合法的产线号{model.ProdLineId}:好运箱产线号必须为 3 或 4"; // LogHelper.Info(info); // return NewMesResult(2, info); //} using (var tran = db.Ado.UseTran()) { if (db.Insertable<TN_CG_Detail>(detail).ExecuteCommand() <= 0) { @@ -1163,12 +1351,6 @@ info = "插入物料信息失败:" + JsonConvert.SerializeObject(detail); return NewMesResult(2, info); } //if (db.Insertable<TN_Loc_Container>(locCntrRel).ExecuteCommand() <= 0) { // tran.RollbackTran(); // info = "插入物料信息失败:" + JsonConvert.SerializeObject(detail); // return NewWmsResult(2, info); //} tran.CommitTran(); } api/ApiModel.cs
@@ -354,6 +354,16 @@ /// </summary> [JsonProperty("qualityGrade")] public string QualityGrade { get; set; } /// <summary> /// 料箱编号(待定) /// </summary> [JsonProperty("cntrCode")] public string CntrCode { get; set; } ///// <summary> ///// 产线号(待定,好运箱有2条产线,对应2个下线货位,这里暂定为:3和4) ///// </summary> //[JsonProperty("prodLineId")] //public string ProdLineId { get; set; } } /// <summary> api/MoboxController.cs
@@ -44,7 +44,7 @@ else if (model.CntrType == "空好运箱") { return ApiHelper.EmptyInboundGoodpack(model); } else { else { // PDA前端下拉选单限制,故理论上不会进入这个流程 return NewSimpleResult(-1, $"容器类型 '{model.CntrType}' 不合法:应为 '空托盘' 或 '空好运箱'"); } } config/config.comment.json
@@ -1,116 +1,74 @@ { "WebApiUrl": "http://192.168.1.141:8901", //WCS自己的地址 "NdcApiUrl": "http://127.0.0.1:5201/api/order/", // //"WebApiUrl": "http://192.168.1.141:8901", "WebApiUrl": "http://127.0.0.1:8901", "NdcApiUrl": "http://127.0.0.1:5201/api/order/", "ErpApiUrl": "http://127.0.0.1:8085/api/", "SqlServer": "Data Source=192.168.1.87;Initial Catalog=AMS_OIMobox;User ID=sa;Password=123456;", "TcpServerIp": "127.0.0.1", "TcpServerPort": 8085, "Areas": [ // 货区 "Areas": [ { "Name": "包装区", "Codes": [ "BZQ" ] }, { "Name": "操作区", "Codes": [ "CZQ1", "CZQ2" ] "Name": "空箱操作区", "Codes": [ "KXCZQ" ] }, { "Name": "货架区", "Codes": [ "HJQ1", "HJQ2", "HJQ3", "HJQ4" ] "Name": "满箱操作区", "Codes": [ "MXCZQ" ] }, { "Name": "空托存放区", "Codes": [ "KTCFQ" ] }, { "Name": "空箱存放区", "Codes": [ "HJQ1" ] "Name": "空箱货架区", "Codes": [ "KXHJQ" ] }, { "Name": "满托存放区", "Codes": [ "HJQ2" ] "Name": "满托货架区", "Codes": [ "MTHJQ" ] }, { "Name": "满箱存放区", "Codes": [ "HJQ3" ] "Name": "满箱货架区", "Codes": [ "MXHJQ" ] }, { "Name": "抽检区", "Codes": [ "CJQ1" ] "Codes": [ "CJQ" ] }, { "Name": "抽检异常区", "Codes": [ "CJYCQ" ] }, { "Name": "空箱操作区", "Codes": [ "CZQ1" ] }, { "Name": "满箱操作区", "Codes": [ "CZQ2" ] }, { "Name": "空托入库接驳区", "Codes": [ "KTRKJBQ" ] "Codes": [ "KTJBQ" ] }, { "Name": "空箱入库接驳区", "Codes": [ "KXRKJBQ1", "KXRKJBQ2" ] "Codes": [ "KXJBQ1", "KXJBQ2" ] }, { "Name": "汽车出库备货区", // 汽车出库月台 "Codes": [ "CKQ-QC" ] // 拼音:出库区-汽车 "Name": "汽车出库区", "Codes": [ "QCCKQ" ] }, { "Name": "火车出库备货区", // 火车出库月台 "Codes": [ "CKQ-HC" ] // 拼音:出库区-火车 "Name": "火车出库区", "Codes": [ "HCCKQ" ] }, { "Name": "汽车备货区", "Codes": [ "QCBHQ" ] }, { "Name": "火车备货区", "Codes": [ "HCBHQ" ] } ], "Tasks": [ { "Name": "托盘-满托下线入库", "StartAreas": [ "BZQ" ], "EndAreas": [ "HJQ2" ] }, { "Name": "好运箱-满箱下线入库", "StartAreas": [ "CZQ2" ], "EndAreas": [ "HJQ3" ] }, { "Name": "托盘-空托上线", "StartAreas": [ "KTCFQ" ], "EndAreas": [ "BZQ" ] }, { "Name": "好运箱-空箱上线", "StartAreas": [ "HJQ1" ], "EndAreas": [ "CZQ1" ] }, { "Name": "托盘-空托入库", "StartAreas": [ "KTRKJBQ" ], "EndAreas": [ "KTCFQ" ] }, { "Name": "好运箱-空箱入库", "StartAreas": [ "KXRKJBQ1" ], "EndAreas": [ "HJQ1" ] }, { "Name": "抽检-出库" }, { "Name": "抽检-合格回库" }, { "Name": "抽检-不合格移库" }, { "Name": "成品胶出库" } ], "ProductionLines": [ // 产线的 "ProductionLines": [ { "Id": "1", "Name": "托盘产线1", core/Monitor.cs
@@ -77,6 +77,7 @@ cntrItemRel = new TN_Container_ItemType { S_ITEM_CODE = itemCode, S_CNTR_CODE = cntrCode, S_CNTR_TYPE = "托盘", }; } // END @@ -207,9 +208,10 @@ } public static void CheckOutboundOrder() { var taskName = TaskName.C成品胶出库; var db = new SqlHelper<object>().GetInstance(); var info = $"轮询--{taskName}--"; var info = ""; var taskName = TaskName.C成品胶出库; try { var orderList = db.Queryable<TN_Outbound_Order>() @@ -218,7 +220,7 @@ .ToList(); if (orderList.Count == 0) { info += $"暂无待执行的{taskName}单"; info = $"轮询:{taskName}:暂无待执行的{taskName}单"; LogHelper.Info(info); return; } @@ -229,7 +231,7 @@ .Count(d => d.S_OO_NO == order.S_NO && d.N_B_STATE >= 2); // 执行中 var allCount = db.Queryable<TN_Outbound_Detail>() .Count(d => d.S_OO_NO == order.S_NO); info += $"统计{taskName}单'{order.S_NO}'任务已下发:{doingCount}/{allCount}"; info = $"轮询:{taskName}:统计{taskName}单'{order.S_NO}'任务已下发:{doingCount}/{allCount}"; LogHelper.Info(info); if (doingCount == allCount) { @@ -243,7 +245,7 @@ .First(); if (lastDetail != null) { info += $"{taskName}单'{order.S_NO}'上一个任务仍在进行中:" + JsonConvert.SerializeObject(lastDetail); info = $"轮询:{taskName}:{taskName}单'{order.S_NO}'上一个任务仍在进行中:" + JsonConvert.SerializeObject(lastDetail); LogHelper.Info(info); continue; } @@ -253,7 +255,7 @@ .First(); if (outboundDetail == null) { info += $"仍有任务未执行完成,但当前没有已下发的任务"; info = $"轮询:{taskName}:仍有任务未执行完成,但当前没有已下发的任务"; LogHelper.Info(info); continue; } @@ -269,13 +271,14 @@ foreach (var detail in detailList) { var startLoc = db.Queryable<TN_Location>() .LeftJoin<TN_Loc_Container>((l, c) => l.S_CODE == c.S_LOC_CODE) .Where((l, c) => c.S_CNTR_CODE == detail.S_CNTR_CODE) .Where((l, c) => c.S_CNTR_CODE == detail.S_CNTR_CODE) // 根据容器号搜索起点货位 .Where(l => l.N_LOCK_STATE == 0 && l.S_LOCK_STATE == "无" && l.C_ENABLE == "Y") // 筛选:未上锁 .Where(l => l.N_CURRENT_NUM == 1) .First(); if (startLoc == null) { LogHelper.Info($"轮询--{taskName}:没有找到合适的起点货位!"); info = $"轮询:{taskName}:没有找到合适的起点货位!"; LogHelper.Info(info); continue; } @@ -285,7 +288,8 @@ .Where(a => a.N_CURRENT_NUM == 0).First(); if (endLoc == null) { LogHelper.Info($"轮询--{taskName}:没有找到合适的终点货位!单号'{detail.S_OO_NO}'要求终点库区为'{detail.S_END_AREA}'"); info = $"轮询:{taskName}:没有找到合适的终点货位!单号'{detail.S_OO_NO}'要求终点库区为'{detail.S_END_AREA}'"; LogHelper.Info(info); continue; } @@ -300,7 +304,7 @@ using (var tran = db.Ado.UseTran()) { if (db.Updateable<TN_Outbound_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) { tran.RollbackTran(); info += $"修改明细表状态为完成--失败!"; info = $"轮询:{taskName}:修改明细表状态为完成--失败!"; LogHelper.Info(info); continue; } @@ -312,7 +316,7 @@ it.T_MODIFY }).ExecuteCommand() <= 0) { tran.RollbackTran(); info += $"生成任务'{taskName}'失败:更新起点货位{startLoc.S_CODE}锁状态失败"; info = $"轮询:{taskName}:生成任务'{taskName}'失败:更新起点货位{startLoc.S_CODE}锁状态失败"; LogHelper.Info(info); continue; } @@ -324,20 +328,20 @@ it.T_MODIFY }).ExecuteCommand() <= 0) { tran.RollbackTran(); info += $"生成任务'{taskName}'失败:更新终点货位{endLoc.S_CODE}锁状态失败"; info = $"轮询:{taskName}:生成任务'{taskName}'失败:更新终点货位{endLoc.S_CODE}锁状态失败"; LogHelper.Info(info); continue; } if (db.Insertable<TN_Task>(task).ExecuteCommand() <= 0) { tran.RollbackTran(); info += $"生成任务'{taskName}'失败,容器号{cntId},起点{startLoc.S_CODE},终点货架{endLoc.S_CODE}"; info = $"轮询:{taskName}:生成任务'{taskName}'失败,容器号{cntId},起点{startLoc.S_CODE},终点货架{endLoc.S_CODE}"; LogHelper.Info(info); continue; } tran.CommitTran(); info += $"生成任务'{taskName}'成功,容器号{cntId},起点{startLoc.S_CODE},终点货架{endLoc.S_CODE}"; info = $"轮询:{taskName}:生成任务'{taskName}'成功,容器号{cntId},起点{startLoc.S_CODE},终点货架{endLoc.S_CODE}"; LogHelper.Info(info); continue; } @@ -376,15 +380,16 @@ } catch (Exception ex) { info += $"发生了异常:{ex.Message}"; info = $"轮询:{taskName}:发生了异常:{ex.Message}"; LogHelper.InfoEx(ex); } } public static void CheckCheckOrder() { var taskName = TaskName.C抽检_出库; var db = new SqlHelper<object>().GetInstance(); var info = ""; var taskName = TaskName.C抽检_出库; try { var orderList = db.Queryable<TN_Spot_Check>() @@ -393,7 +398,7 @@ .ToList(); if (orderList.Count == 0) { LogHelper.Info($"轮询--{taskName}--暂无待执行的{taskName}单"); LogHelper.Info($"轮询:{taskName}:暂无待执行的{taskName}单"); return; } core/WCSCore.cs
@@ -133,25 +133,27 @@ var info = ""; try { var cgDetail = new TN_CG_Detail(); var cgDetail = new TN_CG_Detail(); // 如果没有信息,默认就是空值,可以直接填入,不需要判断 var emptyTask = false; //var emptyTask = false; // 空托/空箱任务 if (task.S_TYPE != TaskName.H好运箱_空箱上线 && task.S_TYPE != TaskName.H好运箱_空箱入库 && task.S_TYPE != TaskName.T托盘_空托上线 && task.S_TYPE != TaskName.T托盘_空托入库) { // 非空托任务(空托任务无法在CGDetail查到物料信息) emptyTask= true; // 非空托/空箱任务(空托/空箱任务无法在CGDetail查到物料信息) //emptyTask= true; cgDetail = db.Queryable<TN_CG_Detail>() .Where(d => d.S_CNTR_CODE == task.S_CNTR_CODE) .First(); if (cgDetail == null) { info = $"任务{task.S_CODE}完成,记录出入库失败:无法在容器货品明细表中找到托盘{task.S_CNTR_CODE}对应的物料"; info = $"任务{task.S_CODE}完成,记录出入库存在问题:无法在容器货品明细表中找到托盘{task.S_CNTR_CODE}对应的物料"; LogHelper.Info(info); return; //return; cgDetail = new TN_CG_Detail() ; cgDetail.S_ITEM_CODE = "异常"; } } var isInbound = false; var isInbound = false; // 入库类型的任务(包括移库类任务) var inboundTasks = new List<string> { TaskName.H好运箱_满箱下线入库, TaskName.H好运箱_空箱入库, TaskName.T托盘_满托下线入库, TaskName.T托盘_空托入库, TaskName.C抽检_合格回库, TaskName.C抽检_不合格移库, TaskName.Y移库 @@ -177,6 +179,8 @@ N_QTY = cgDetail.N_ITEM_NUM, }; // 数据库操作 if (db.Insertable<TN_Record_Table>(record).ExecuteCommand() <= 0) { info = "插入出入库记录表失败:" + JsonConvert.SerializeObject(record); LogHelper.Info(info); @@ -191,6 +195,11 @@ } } /// <summary> /// AGV产线安全交互逻辑实现 /// </summary> /// <param name="model"></param> /// <returns></returns> public static ReturnResult SafetyInteraction(SafetyInteractionInfo model) { var db = new SqlHelper<object>().GetInstance(); var info = ""; @@ -358,8 +367,6 @@ else { LogHelper.Info("暂无任务"); } } } } models/TN_Container.cs
@@ -10,6 +10,10 @@ public class TN_Container : BaseModel { public string S_CODE { get; set; } public string S_TYPE { get; set; } public string S_SPEC { get; set; } public int N_DETAIL_COUNT { get; set; } [SugarColumn(IsIgnore = true)] models/TN_Container_ItemType.cs
@@ -16,8 +16,8 @@ /// </remarks> [SugarTable("TN_Container_ItemType")] public class TN_Container_ItemType : BaseModel { public string S_CNTR_CODE { get; set; } public string S_CNTR_TYPE { get; set; } public string S_ITEM_CODE { get; set; } public string S_CNTR_CODE { get; set; } = string.Empty; public string S_CNTR_TYPE { get; set; } = string.Empty; public string S_ITEM_CODE { get; set; } = string.Empty; } } wms/LocationHelper.cs
@@ -127,13 +127,19 @@ } /// <summary> /// 起点出库锁 /// 起点出库锁(只能对无锁货位上锁) /// </summary> /// <param name="loc"></param> /// <param name="lockSource"></param> /// <returns></returns> public static bool LockStartLoc(ref TN_Location loc, string lockSource = "") { if (loc == null || loc.N_LOCK_STATE != 0) { if (loc == null) { LogHelper.Info($"起点出库锁:传入的货位参数为null"); return false; } if (loc.N_LOCK_STATE != 0 || loc.S_LOCK_STATE != "无") { LogHelper.Info($"起点出库锁:货位当前已有锁({loc.N_LOCK_STATE},{loc.S_LOCK_STATE})"); return false; } @@ -148,7 +154,13 @@ } public static bool LockEndLoc(ref TN_Location loc, string lockSource = "") { if (loc == null || loc.N_LOCK_STATE != 0) { if (loc == null) { LogHelper.Info($"终点入库锁:传入的货位参数为null"); return false; } if (loc.N_LOCK_STATE != 0 || loc.S_LOCK_STATE != "无") { LogHelper.Info($"终点入库锁:货位当前已有锁({loc.N_LOCK_STATE},{loc.S_LOCK_STATE})"); return false; } @@ -313,9 +325,17 @@ var bindLocCntList = new List<TN_Loc_Container>(); foreach (var item in cntrs) { bindLocCntList.Add(new TN_Loc_Container() { S_LOC_CODE = loc, S_CNTR_CODE = item }); // 针对容器类型添加的新逻辑 var cntrItemRel = db.Queryable<TN_Container_ItemType>() .Where(c => c.S_CNTR_CODE == item).First(); if (cntrItemRel == null) { LogHelper.Info($"货位解绑时,容器{item}没有在容器物料信息关系表中查到"); bindLocCntList.Add(new TN_Loc_Container() { S_LOC_CODE = loc, S_CNTR_CODE = item }); } else { bindLocCntList.Add(new TN_Loc_Container() { S_LOC_CODE = loc, S_CNTR_CODE = item, S_CNTR_TYPE = cntrItemRel.S_CNTR_TYPE }); } } var log = JsonConvert.SerializeObject(bindLocCntList);