| | |
| | | using HH.WCS.Mobox3.AnGang.AppStart; |
| | | using HH.WCS.Mobox3.AnGang.config; |
| | | using System; |
| | | |
| | | using HH.WCS.Mobox3.AnGang.AppStart; |
| | | using HH.WCS.Mobox3.AnGang.Consts; |
| | | using HH.WCS.Mobox3.AnGang.Helper; |
| | | using HH.WCS.Mobox3.AnGang.Helpers; |
| | | using HH.WCS.Mobox3.AnGang.Models; |
| | | |
| | | using Newtonsoft.Json; |
| | | using System; |
| | | |
| | | using static HH.WCS.Mobox3.AnGang.Dtos.Request.ErpRequest; |
| | | using static HH.WCS.Mobox3.AnGang.Dtos.Request.MoboxRequest; |
| | | using static HH.WCS.Mobox3.AnGang.Dtos.Response.MoboxResponse; |
| | | using static HH.WCS.Mobox3.AnGang.Helpers.ResultHelper; |
| | | |
| | | namespace HH.WCS.Mobox3.AnGang.Services { |
| | | public class MoboxService { |
| | |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | internal static SimpleResult InWarehouse(InWarehouseInfo model) { |
| | | internal static SimpleResult Inbound(InboundInfo model) { |
| | | LogHelper.Info("触发API:产品入库(PDA)" + JsonConvert.SerializeObject(model), "API"); |
| | | var db = DbHelper.GetDbClient(); |
| | | var startLoc = new TN_Location(); |
| | | //var endLoc = new TN_Location(); |
| | | |
| | | try { |
| | | // 起点位置必须:为空、无锁、启用、属于收发区域 |
| | | startLoc = db.Queryable<TN_Location>(). |
| | | First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_SHELF_CODE == AreaCode.收发货位区); |
| | | First(a => a.S_CODE == model.StartLoc |
| | | && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" |
| | | && a.S_AREA_CODE == AreaCode.收发区); |
| | | |
| | | if (startLoc == null) { |
| | | return BuildSimpleResult(1, $"起点位置{model.startLoc}不存在!"); |
| | | return BuildSimpleResult(1, $"起点位置{model.StartLoc}不存在!"); |
| | | } |
| | | |
| | | //if (!LocationHelper.IsStartLocationTransferOk(model.startLoc, |
| | | // a => a.S_SHELF_CODE == Settings.Areas[0], |
| | | // out startLoc)) { |
| | | // return BuildSimpleResult(1, $"起点位置{model.startLoc}不存在!"); |
| | | //} |
| | | |
| | | // 容器 ID 和 物料 ID 未指定,由系统直接生成 |
| | | var cntID = Guid.NewGuid().ToString("D"); |
| | |
| | | S_CNTR_CODE = cntID, |
| | | }; |
| | | |
| | | var endArea = ""; // 默认终点区域为空 |
| | | var endLoc = "0"; // 假的默认终点地址 |
| | | |
| | | // 指定货位排号(不能为空、空字符串或空格) |
| | | if (model.endShelf != null && model.endShelf.Trim() != "") { |
| | | endArea = model.endShelf; |
| | | // 没有在配置文件找到这个货架号 |
| | | if (!Settings.AreaMap[AreaName.货架区].Contains(endArea)) { |
| | | return BuildSimpleResult(2, $"货架号 {model.endShelf} 不存在"); |
| | | if (model.Row != null && model.Row.Trim() != "") { |
| | | endLoc = model.Row; // 用排号字符串当做假地址 |
| | | if (!int.TryParse(model.Row.Trim(), out int row)) { |
| | | return BuildSimpleResult(2, $"{model.Row} 不合法:无法转成整数类型"); |
| | | } |
| | | // 货架排号只能是 0 - 8 |
| | | if (row <= 0 || row > 8) { |
| | | return BuildSimpleResult(2, $"货架号 {model.Row} 必须是1-8之间的整数"); |
| | | } |
| | | } |
| | | |
| | |
| | | if (db.Insertable<TN_Loc_Container>(cntLoc).ExecuteCommand() > 0 |
| | | && db.Insertable<TN_CG_Detail>(cgCnt).ExecuteCommand() > 0) { |
| | | //创建产品入库任务:创建搬送任务,起点终点容器 |
| | | if (WCSHelper.CreateTaskWithArea(startLoc.S_CODE, endArea, "产品入库(PDA)", 3, cntID)) { |
| | | if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc, TaskName.产品入库, 3, cntID)) { |
| | | //如果操作TN_Location会造成死锁 |
| | | LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁, |
| | | //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁 |
| | | |
| | | trans.CommitTran(); |
| | | |
| | | return BuildSimpleResult(0, $"生成 产品入库(PDA) 成功,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endArea} ,终点货位未指定"); |
| | | return BuildSimpleResult(0, $"生成 产品入库 成功,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc} ,终点货位未指定"); |
| | | } |
| | | else { |
| | | trans.RollbackTran(); |
| | | |
| | | return BuildSimpleResult(5, $"生成 产品入库(PDA) 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endArea} ,终点货位未指定"); |
| | | return BuildSimpleResult(5, $"生成 产品入库 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc} ,终点货位未指定"); |
| | | } |
| | | } |
| | | else { |
| | |
| | | |
| | | try { |
| | | // 任务号存在:终点货架和终点位置为空,且任务为产品入库(PDA) |
| | | //var task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.taskNo && a.S_END_AREA == "" && a.S_END_LOC == "" && a.S_TYPE == "产品入库(PDA)"); |
| | | var task = db.Queryable<TN_Task>().First(a => a.S_EQ_NO == model.forklift_no && a.S_END_AREA == "" && a.S_END_LOC == "" && a.S_TYPE == "产品入库(PDA)"); |
| | | //var task = db.Queryable<TN_Task>().First(a => a.S_EQ_NO == model.forklift_no && a.S_END_AREA == "HJQ" && a.S_END_LOC == "0" && a.S_TYPE == "产品入库(PDA)"); |
| | | var task = db.Queryable<TN_Task>() |
| | | .Where(a => a.S_B_STATE == "取货完成" && a.S_TYPE == TaskName.产品入库) |
| | | .OrderBy(a => a.T_CREATE, SqlSugar.OrderByType.Desc).First(); |
| | | |
| | | if (task == null) { |
| | | //return BuildSimpleResult(2, $"任务号 {model.taskNo} 不存在,或不满足终点货架为空、终点位置为空且为 产品入库(PDA) 任务"); |
| | | return BuildSimpleResult(2, $"小车 '{model.forklift_no}' 当前不存在任务,或不满足终点货架为空、终点位置为空且为 产品入库(PDA) 任务"); |
| | | return BuildSimpleResult(2, $"当前不存在状态为 取货完成 的 产品入库 任务"); |
| | | } |
| | | |
| | | if (task.S_END_LOC != null && task.S_END_LOC != "0") { |
| | | return BuildSimpleResult(3, $"该任务已有终点"); |
| | | } |
| | | |
| | | var cgDetail = db.Queryable<TN_CG_Detail>() |
| | | .Where(a => a.S_CNTR_CODE == task.S_CNTR_CODE).First(); |
| | | |
| | | if (cgDetail == null) { |
| | | return BuildSimpleResult(4, $"托盘物料不存在"); |
| | | } |
| | | |
| | | var endLoc = new TN_Location(); |
| | | if (task.F_WEIGHT > 1500) { |
| | | if (cgDetail.F_QTY > 1500) { |
| | | // 重量超过1.5t,需要选择1-3层货架 |
| | | endLoc = db.Queryable<TN_Location>().First( |
| | | a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 && a.N_HEIGHT <= 3); |
| | | a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 && a.N_LAYER <= 3 && a.S_AREA_CODE == AreaCode.货架区); |
| | | } |
| | | else if (cgDetail.F_QTY > 0) { |
| | | endLoc = db.Queryable<TN_Location>().First( |
| | | a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 && a.S_AREA_CODE == AreaCode.货架区); |
| | | } |
| | | else { |
| | | endLoc = db.Queryable<TN_Location>().First( |
| | | a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0); |
| | | return BuildSimpleResult(5, $"物料重量信息不合法:{cgDetail.F_QTY}"); |
| | | } |
| | | |
| | | // 没有符合条件的货位 |
| | | if (endLoc == null) { |
| | | return BuildSimpleResult(3, $"货位{model.endLoc}不满足要求:不存在或不满足称重放置要求"); |
| | | return BuildSimpleResult(6, $"货位{model.endLoc}不存在,或不满足称重放置要求"); |
| | | } |
| | | |
| | | // 修改任务终点为PDA指定终点 |
| | | task.S_END_LOC = endLoc.S_CODE; |
| | | task.S_END_AREA = endLoc.S_SHELF_CODE; |
| | | |
| | | using (var trans = db.Ado.UseTran()) { |
| | | if (db.Updateable<TN_Task>(task).ExecuteCommand() > 0) { |
| | | if (db.Updateable<TN_Task>(task).UpdateColumns(a => a.S_END_LOC).ExecuteCommand() > 0) { |
| | | LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁 |
| | | trans.CommitTran(); |
| | | |
| | |
| | | else { |
| | | trans.RollbackTran(); |
| | | |
| | | return BuildSimpleResult(4, $"任务{task.S_CODE}修改失败,修改终点位置为{endLoc.S_CODE}"); |
| | | return BuildSimpleResult(7, $"任务{task.S_CODE}修改失败,修改终点位置为{endLoc.S_CODE}"); |
| | | } |
| | | } |
| | | } |
| | |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | internal static SimpleResult PartOutWarehouse(PartOutWarehouseInfo model) { |
| | | internal static SimpleResult PartOutbound(PartOutboundInfo model) { |
| | | LogHelper.Info("触发API:产品部分出库(WMS)" + JsonConvert.SerializeObject(model), "API"); |
| | | var db = DbHelper.GetDbClient(); |
| | | |
| | |
| | | return BuildSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可出库的物料"); |
| | | } |
| | | |
| | | var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区); |
| | | var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发区); |
| | | |
| | | if (endLoc == null) { |
| | | return BuildSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件"); |
| | |
| | | |
| | | using (var trans = db.Ado.UseTran()) { |
| | | // 解绑:起点货位与待搬运容器(不需要手动deleteable操作,内部会自动操作的) |
| | | if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "产品部分出库(WMS)", 3, locCtnrRel.S_CNTR_CODE))//创建搬送任务,起点终点容器 |
| | | if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, TaskName.产品部分出库, 3, locCtnrRel.S_CNTR_CODE))//创建搬送任务,起点终点容器 |
| | | {//如果操作TN_Location会造成死锁 |
| | | LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁, |
| | | LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁 |
| | | |
| | | trans.CommitTran(); |
| | | return BuildSimpleResult(0, $"生成 产品出库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}"); |
| | | return BuildSimpleResult(0, $"生成 产品部分出库 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}"); |
| | | } |
| | | else { |
| | | trans.RollbackTran(); |
| | | return BuildSimpleResult(5, $"生成 产品出库(WMS) 失败,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}"); |
| | | return BuildSimpleResult(5, $"生成 产品部分出库 失败,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}"); |
| | | } |
| | | } |
| | | } |
| | |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | internal static SimpleResult PartInWarehouse(PartInWarehouseInfo model) { |
| | | internal static SimpleResult PartInbound(PartInboundInfo model) { |
| | | LogHelper.Info("触发API:产品部分回库(WMS)" + JsonConvert.SerializeObject(model), "API"); |
| | | var db = DbHelper.GetDbClient(); |
| | | |
| | | try { |
| | | // 起点位置:取放货区(有货物、没有锁、已启用) |
| | | var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区); |
| | | var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发区); |
| | | if (startLoc == null) { |
| | | return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合回库条件"); |
| | | } |
| | |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | internal static SimpleResult CheckOutWarehouse(CheckOutWarehouseInfo model) { |
| | | internal static SimpleResult CheckOutbound(CheckOutboundInfo model) { |
| | | LogHelper.Info("触发API:盘点理货出库(WMS)" + JsonConvert.SerializeObject(model), "API"); |
| | | var db = DbHelper.GetDbClient(); |
| | | |
| | | try { |
| | | // 起点位置:取放货区(有货物、没有锁、已启用) |
| | | var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区); |
| | | var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发区); |
| | | if (startLoc == null) { |
| | | return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合出库条件"); |
| | | } |
| | |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | internal static SimpleResult CheckInWarehouse(CheckInWarehouseInfo model) { |
| | | internal static SimpleResult CheckInbound(CheckInboundInfo model) { |
| | | LogHelper.Info("触发API:盘点理货回库(WMS)" + JsonConvert.SerializeObject(model), "API"); |
| | | var db = DbHelper.GetDbClient(); |
| | | |
| | | try { |
| | | // 起点位置:取放货区(有货物、没有锁、已启用) |
| | | var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区); |
| | | var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发区); |
| | | if (startLoc == null) { |
| | | return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合回库条件"); |
| | | } |
| | |
| | | catch (Exception ex) { |
| | | return BuildSimpleResult(1, $"发生了异常:{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 入库数据同步(ERP) |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | internal static SimpleResult InWarehouseDataSync(InWarehouseDataSyncInfo model) { |
| | | return BuildSimpleResult(0, ""); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 出库发料同步(ERP) |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | internal static SimpleResult OutWarehouseDataSync(OutWarehouseDataSyncInfo model) { |
| | | return BuildSimpleResult(0, ""); |
| | | } |
| | | } |
| | | } |