优化代码, 封装货位锁和创建任务流程, 数据库事务等
| | |
| | | <Compile Include="dispatch\HostToAGV.cs" /> |
| | | <Compile Include="util\LogHelper.cs" /> |
| | | <Compile Include="util\WebHelper.cs" /> |
| | | <Compile Include="wms\DbTranHelper.cs" /> |
| | | <Compile Include="wms\LocationHelper.cs" /> |
| | | <Compile Include="wms\SYSHelper.cs" /> |
| | | <Compile Include="Program.cs" /> |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Threading; |
| | | using HH.WCS.Mobox3.DSZSH.device; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.core; |
| | | using HH.WCS.Mobox3.DSZSH.device; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Microsoft.Owin.Hosting; |
| | | |
| | | using Topshelf; |
| | | |
| | | using Task = System.Threading.Tasks.Task; |
| | | using Monitor = HH.WCS.Mobox3.DSZSH.core.Monitor; |
| | | using System.Net.Sockets; |
| | | using Task = System.Threading.Tasks.Task; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH { |
| | | internal class Program |
| | |
| | | using System.Web.Http; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.core; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Security.Cryptography; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.core; |
| | | using HH.WCS.Mobox3.DSZSH.models; |
| | |
| | | using HH.WCS.Mobox3.DSZSH.wms; |
| | | |
| | | using Newtonsoft.Json; |
| | | |
| | | using SqlSugar; |
| | | |
| | | using Swashbuckle.Swagger; |
| | |
| | | } |
| | | |
| | | // 更新[起点/终点]锁状态,创建任务 |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, locCntrRel.S_CNTR_CODE, taskInfo.TaskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, locCntrRel.S_CNTR_CODE, taskInfo.TaskName); |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | // 删除/更新旧[货位/容器/物料]信息 |
| | |
| | | } |
| | | |
| | | // 起点终点上锁,创建任务 |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, locCntrRel.S_CNTR_CODE, taskInfo.TaskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, locCntrRel.S_CNTR_CODE, taskInfo.TaskName); |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (old.CgDetail != null && db.Deleteable(old.CgDetail).ExecuteCommand() <= 0) { |
| | |
| | | return NewSimpleResult(3, preLog + $"没有找到合适的终点货位!要求:锁状态='无';当前容器数量=0;所在库区={LogObject(taskInfo.EndAreas)}"); |
| | | } |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, locCntrRel.S_CNTR_CODE, taskInfo.TaskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, locCntrRel.S_CNTR_CODE, taskInfo.TaskName); |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (old.CgDetail != null && db.Deleteable(old.CgDetail).ExecuteCommand() <= 0) { |
| | |
| | | return NewSimpleResult(5, preLog + $"没有找到合适的终点货位!要求:锁状态='无';当前容器数量=0;所在库区={LogObject(taskInfo.EndAreas)}"); |
| | | } |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, model.CntId, taskInfo.TaskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, model.CntId, taskInfo.TaskName); |
| | | |
| | | cntr.S_SOURCE = task.S_CODE; // 用任务号作为容器更新的依据 |
| | | cntr.T_MODIFY = DateTime.Now; |
| | |
| | | return NewSimpleResult(3, preLog + $"没有找到合适的终点货位!要求:锁状态='无',当前容器数量=0,所在库区={LogObject(taskInfo.EndAreas)}"); |
| | | } |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, model.CntId, taskInfo.TaskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, model.CntId, taskInfo.TaskName); |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | // 更新[起点/终点]锁状态,创建任务 |
| | |
| | | cgDetail.T_MODIFY = DateTime.Now; |
| | | |
| | | var cntId = locCntrRel.S_CNTR_CODE; |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskInfo.TaskName); |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, cntId, taskInfo.TaskName); |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (db.Updateable(cgDetail).UpdateColumns(it => new { it.N_ITEM_STATE, it.S_ITEM_STATE, it.T_MODIFY }).ExecuteCommand() <= 0) { |
| | |
| | | cgDetail.N_ITEM_STATE = 2; |
| | | cgDetail.S_ITEM_STATE = "不合格"; |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, locCntrRel.S_CNTR_CODE, taskInfo.TaskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, locCntrRel.S_CNTR_CODE, taskInfo.TaskName); |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (db.Updateable(cgDetail).UpdateColumns(it => new { it.N_ITEM_STATE, it.S_ITEM_STATE }).ExecuteCommand() <= 0) { |
| | |
| | | |
| | | var cntId = locCntrRel.S_CNTR_CODE; |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskInfo.TaskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, cntId, taskInfo.TaskName); |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | //if (db.Insertable(locCntrRel).ExecuteCommand() <= 0) { |
| | |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.api { |
| | |
| | | |
| | | using static HH.WCS.Mobox3.DSZSH.api.ApiModel; |
| | | using static HH.WCS.Mobox3.DSZSH.api.OtherModel; |
| | | using static HH.WCS.Mobox3.DSZSH.Config; |
| | | using static HH.WCS.Mobox3.DSZSH.core.Monitor; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.api { |
| | |
| | | using System.Collections.Generic; |
| | | using System.Web.Http; |
| | | using static HH.WCS.Mobox3.DSZSH.api.OtherModel; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.api { |
| | | /// <summary> |
| | |
| | | using System.Web.Http; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.models; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | |
| | |
| | | using Newtonsoft.Json; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | using System.Collections.Generic; |
| | | using System.Web.Http; |
| | | |
| | |
| | | |
| | | public static void CheckInbound() { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var info = ""; |
| | | |
| | | try { |
| | | // 查产线是否有物料信息 |
| | | foreach (var prod in Settings.ProductionLines) { |
| | |
| | | // TCPClient传递信息的时候,不要用断点阻塞程序 |
| | | // {"item_code":"CG1001","batch_no":"BN1001","cntr_code":"CN2505111"} |
| | | if (!TcpClientHelper.TryReadProductionLine(out byte[] read)) { |
| | | info = $"测试{prod.Id}号产线{prod.PlcIp}:{prod.PlcPort}:读取产线信息失败"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info($"测试{prod.Id}号产线{prod.PlcIp}:{prod.PlcPort}:读取产线信息失败"); |
| | | continue; |
| | | } |
| | | |
| | |
| | | |
| | | var cntId = detail.S_CNTR_CODE; |
| | | |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, cntId, taskName); |
| | | task.S_OP_CODE = detail.S_OO_NO; |
| | | if (string.IsNullOrEmpty(detail.S_BS_NO)) { |
| | | task.S_BS_NO = detail.S_BS_NO; |
| | | task.S_BS_TYPE = "ERP"; |
| | | } |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); // 起点出库锁 |
| | | WCSHelper.LockEndLoc(ref endLoc); // 终点入库锁 |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (db.Updateable(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) { |
| | |
| | | |
| | | public static void CheckCheckOrder() { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var info = ""; |
| | | |
| | | var taskInfo = Settings.GetTaskInfo(ETask.C抽检出库); |
| | | var taskName = taskInfo.TaskName; |
| | | const string preLog = "轮询:抽检:"; |
| | |
| | | try { |
| | | var orderList = db.Queryable<TN_Spot_Check>().Where(c => c.N_B_STATE == 1).OrderBy(c => c.T_CREATE).ToList(); |
| | | if (orderList.Count == 0) { |
| | | LogHelper.Debug($"轮询:{taskName}:暂无待执行的{taskName}单"); |
| | | LogHelper.Debug(preLog + $"暂无待执行的{taskName}单"); |
| | | return; |
| | | } |
| | | |
| | |
| | | .ToList(); |
| | | |
| | | if (checkDetailList.Count == 0) { |
| | | LogHelper.Info($"轮询:{taskName}:仍有任务未执行完成,但当前没有已下发的任务"); |
| | | LogHelper.Info(preLog + $"仍有任务未执行完成,但当前没有已下发的任务"); |
| | | continue; |
| | | } |
| | | |
| | |
| | | .Where((l, c) => c.S_CNTR_CODE == detail.S_CNTR_CODE).First(); |
| | | |
| | | if (startLoc == null) { |
| | | LogHelper.Info($"轮询:{taskName}:没有找到合适的起点货位!"); |
| | | LogHelper.Info(preLog + $"没有找到合适的起点货位!"); |
| | | continue; |
| | | } |
| | | |
| | |
| | | .Where(a => a.N_CURRENT_NUM == 0).First(); |
| | | |
| | | if (endLoc == null) { |
| | | LogHelper.Info($"轮询:{taskName}:没有找到合适的终点货位!"); |
| | | LogHelper.Info(preLog + $"没有找到合适的终点货位!"); |
| | | continue; |
| | | } |
| | | |
| | | detail.N_B_STATE = 2; |
| | | |
| | | var cntId = detail.S_CNTR_CODE; |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName); |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, cntId, taskName); |
| | | task.S_OP_CODE = detail.S_OO_NO; |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); |
| | | WCSHelper.LockEndLoc(ref endLoc); |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (db.Updateable(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | LogHelper.Info(preLog + $"修改{taskName}单明细表状态为完成--失败!"); |
| | | continue; |
| | | } |
| | | |
| | | if (db.Updateable(startLoc).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY, it.N_CURRENT_NUM, }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | LogHelper.Info(preLog + $"更新[起点货位锁状态]失败!起点='{startLoc.S_CODE}',锁状态=>'出库锁'"); |
| | | continue; |
| | | } |
| | | |
| | | if (db.Updateable(endLoc).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY, }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | LogHelper.Info(preLog + $"更新[终点货位锁状态]失败!终点='{endLoc.S_CODE}',锁状态=>'入库锁'"); |
| | | continue; |
| | | } |
| | | |
| | | if (db.Insertable(task).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | LogHelper.Info(preLog + $"生成任务'{taskName}'失败,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"); |
| | | continue; |
| | | } |
| | | |
| | | tran.CommitTran(); |
| | | LogHelper.Info(preLog + $"生成任务'{taskName}'成功,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"); |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.InfoEx(ex, preLog); |
| | | } |
| | | } |
| | | |
| | | public static void CheckShiftOrder() { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var taskInfo = Settings.GetTaskInfo(ETask.Y移库); |
| | | var taskName = taskInfo.TaskName; |
| | | const string preLog = "轮询:移库:"; |
| | | |
| | | try { |
| | | var orderList = db.Queryable<TN_Relocation_List>() |
| | | .Where(c => c.N_B_STATE == 1) |
| | | .OrderBy(c => c.T_CREATE, SqlSugar.OrderByType.Asc) |
| | | .ToList(); |
| | | |
| | | if (orderList.Count == 0) { |
| | | LogHelper.Debug(preLog + $"暂无待执行的{taskName}单"); |
| | | return; |
| | | } |
| | | |
| | | var detailList = new List<TN_RelocationList_Detail>(); |
| | | foreach (var order in orderList) { |
| | | var doingCount = db.Queryable<TN_RelocationList_Detail>() |
| | | .Count(d => d.S_OO_NO == order.S_NO && d.N_B_STATE >= 2); // 执行中 |
| | | var allCount = db.Queryable<TN_RelocationList_Detail>() |
| | | .Count(d => d.S_OO_NO == order.S_NO); |
| | | LogHelper.Info(preLog + $"统计{taskName}单={order.S_NO}任务已下发:{doingCount}/{allCount}"); |
| | | |
| | | if (doingCount == allCount) { |
| | | order.N_B_STATE = 2; // 所有任务都已执行 |
| | | db.Updateable(order).UpdateColumns(it => new { it.N_B_STATE }).ExecuteCommand(); |
| | | continue; |
| | | } |
| | | |
| | | var checkDetailList = db.Queryable<TN_RelocationList_Detail>() |
| | | .Where(a => a.S_OO_NO == order.S_NO && a.N_B_STATE == 1) // 已下发 |
| | | .ToList(); |
| | | |
| | | if (checkDetailList.Count == 0) { |
| | | LogHelper.Info(preLog + $"仍有任务未执行完成,但当前没有已下发的任务"); |
| | | continue; |
| | | } |
| | | |
| | | foreach (var checkDetail in checkDetailList) { |
| | | detailList.Add(checkDetail); |
| | | } |
| | | } |
| | | |
| | | 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 => 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(preLog + $"没有找到终点货位={detail.S_END_AREA}的终点货位!需要满足:未上锁,当前容器数量=0"); |
| | | continue; |
| | | } |
| | | |
| | | var endLoc = db.Queryable<TN_Location>() |
| | | .Where(l => l.S_AREA_CODE == detail.S_END_AREA) |
| | | .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y") // 筛选:未上锁 |
| | | .Where(a => a.N_CURRENT_NUM == 0).First(); |
| | | |
| | | if (endLoc == null) { |
| | | LogHelper.Info(preLog + $"没有找到终点货位={detail.S_END_AREA}的终点货位!需要满足:未上锁,当前容器数量=0"); |
| | | continue; |
| | | } |
| | | |
| | | detail.N_B_STATE = 2; |
| | | |
| | | var cntId = detail.S_CNTR_CODE; |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, cntId, taskName); |
| | | task.S_OP_CODE = detail.S_OO_NO; |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (db.Updateable(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) { |
| | |
| | | |
| | | if (db.Insertable(task).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"生成任务'{taskName}'失败,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info(preLog + $"生成任务'{taskName}'失败,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"); |
| | | continue; |
| | | } |
| | | |
| | | tran.CommitTran(); |
| | | info = $"生成任务'{taskName}'成功,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"; |
| | | LogHelper.Info(info); |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.InfoEx(ex, preLog); |
| | | } |
| | | } |
| | | |
| | | public static void CheckShiftOrder() { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var info = ""; |
| | | |
| | | var taskInfo = Settings.GetTaskInfo(ETask.Y移库); |
| | | var taskName = taskInfo.TaskName; |
| | | const string preLog = "轮询:移库:"; |
| | | |
| | | try { |
| | | var orderList = db.Queryable<TN_Relocation_List>() |
| | | .Where(c => c.N_B_STATE == 1) |
| | | .OrderBy(c => c.T_CREATE, SqlSugar.OrderByType.Asc) |
| | | .ToList(); |
| | | |
| | | if (orderList.Count == 0) { |
| | | LogHelper.Debug($"轮询:{taskName}:暂无待执行的{taskName}单"); |
| | | return; |
| | | } |
| | | |
| | | var detailList = new List<TN_RelocationList_Detail>(); |
| | | foreach (var order in orderList) { |
| | | var doingCount = db.Queryable<TN_RelocationList_Detail>() |
| | | .Count(d => d.S_OO_NO == order.S_NO && d.N_B_STATE >= 2); // 执行中 |
| | | var allCount = db.Queryable<TN_RelocationList_Detail>() |
| | | .Count(d => d.S_OO_NO == order.S_NO); |
| | | LogHelper.Info($"轮询:{taskName}:统计{taskName}单={order.S_NO}任务已下发:{doingCount}/{allCount}"); |
| | | |
| | | if (doingCount == allCount) { |
| | | order.N_B_STATE = 2; // 所有任务都已执行 |
| | | db.Updateable(order).UpdateColumns(it => new { it.N_B_STATE }).ExecuteCommand(); |
| | | continue; |
| | | } |
| | | |
| | | var checkDetailList = db.Queryable<TN_RelocationList_Detail>() |
| | | .Where(a => a.S_OO_NO == order.S_NO && a.N_B_STATE == 1) // 已下发 |
| | | .ToList(); |
| | | |
| | | if (checkDetailList.Count == 0) { |
| | | LogHelper.Info($"轮询:{taskName}:仍有任务未执行完成,但当前没有已下发的任务"); |
| | | continue; |
| | | } |
| | | |
| | | foreach (var checkDetail in checkDetailList) { |
| | | detailList.Add(checkDetail); |
| | | } |
| | | } |
| | | |
| | | 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 => l.N_LOCK_STATE == 0 && l.S_LOCK_STATE == "无" && l.C_ENABLE == "Y") // 筛选:未上锁 |
| | | .Where(l => l.N_CURRENT_NUM == 1) |
| | | .First(); |
| | | |
| | | if (startLoc == null) { |
| | | info = $"轮询:{taskName}:没有找到容器号={detail.S_CNTR_CODE}的起点货位!需要满足:未上锁,当前容器数量=1"; |
| | | LogHelper.Info(info); |
| | | continue; |
| | | } |
| | | |
| | | var endLoc = db.Queryable<TN_Location>() |
| | | .Where(l => l.S_AREA_CODE == detail.S_END_AREA) |
| | | .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y") // 筛选:未上锁 |
| | | .Where(a => a.N_CURRENT_NUM == 0).First(); |
| | | |
| | | if (endLoc == null) { |
| | | info = $"轮询:{taskName}:没有找到终点货位={detail.S_END_AREA}的终点货位!需要满足:未上锁,当前容器数量=0"; |
| | | LogHelper.Info(info); |
| | | continue; |
| | | } |
| | | |
| | | detail.N_B_STATE = 2; |
| | | |
| | | var cntId = detail.S_CNTR_CODE; |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName); |
| | | task.S_OP_CODE = detail.S_OO_NO; |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); // 起点出库锁 |
| | | WCSHelper.LockEndLoc(ref endLoc); // 终点入库锁 |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (db.Updateable(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | LogHelper.Info($"轮询:{taskName}:修改{taskName}单明细表状态为完成--失败!"); |
| | | continue; |
| | | } |
| | | |
| | | if (db.Updateable(startLoc).UpdateColumns(it => new { |
| | | it.N_LOCK_STATE, |
| | | it.S_LOCK_STATE, |
| | | it.S_LOCK_OP, |
| | | it.T_MODIFY, |
| | | it.N_CURRENT_NUM, // 起点货位绑定后,将货位状态更新 |
| | | }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"生成任务'{taskName}'失败:更新起点货位{startLoc.S_CODE}锁状态失败"; |
| | | LogHelper.Info(info); |
| | | continue; |
| | | } |
| | | |
| | | if (db.Updateable(endLoc).UpdateColumns(it => new { |
| | | it.N_LOCK_STATE, |
| | | it.S_LOCK_STATE, |
| | | it.S_LOCK_OP, |
| | | it.T_MODIFY, |
| | | }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"生成任务'{taskName}'失败:更新终点货位{endLoc.S_CODE}锁状态失败"; |
| | | LogHelper.Info(info); |
| | | continue; |
| | | } |
| | | |
| | | if (db.Insertable(task).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"生成任务'{taskName}'失败,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"; |
| | | LogHelper.Info(info); |
| | | continue; |
| | | } |
| | | |
| | | tran.CommitTran(); |
| | | info = $"生成任务'{taskName}'成功,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info(preLog + $"生成任务'{taskName}'成功,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"); |
| | | continue; |
| | | } |
| | | } |
| | |
| | | |
| | | public static void CreateTaskReturnErp(TN_Task task) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var info = ""; |
| | | var httpH = new HttpHelper(); |
| | | |
| | | try { |
| | |
| | | .First(); |
| | | |
| | | if (plan == null) { |
| | | info = $"计划单号{task.S_BS_NO}不存在!"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info($"计划单号{task.S_BS_NO}不存在!"); |
| | | } |
| | | |
| | | var cgDetail = db.Queryable<TN_CG_Detail>() |
| | |
| | | .First(); |
| | | |
| | | if (cgDetail == null) { |
| | | info = $"物料编码不存在!"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info($"计划单号{task.S_BS_NO}不存在!"); |
| | | } |
| | | |
| | | var model = new OtherModel.CreateTaskReturnErpInfo { |
| | |
| | | plan.HWZT = model.hwzt; |
| | | plan.PH = model.ph; |
| | | var success = db.Updateable(plan).UpdateColumns(p => new { p.HW, p.HWZT, p.PH }).ExecuteCommand() > 0; |
| | | info = "更新出库计划单记录表" + (success ? "成功" : "失败"); |
| | | LogHelper.Info(info); |
| | | LogHelper.Info("更新出库计划单记录表" + (success ? "成功" : "失败")); |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.InfoEx(ex); |
| | |
| | | |
| | | private static void RecordTaskTable(TN_Task task) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var info = ""; |
| | | |
| | | try { |
| | | var cgDetail = new TN_CG_Detail(); // 如果没有信息,默认就是空值,可以直接填入,不需要判断 |
| | |
| | | .First(); |
| | | |
| | | if (cgDetail == null) { |
| | | info = $"任务{task.S_CODE}完成,记录出入库存在问题:无法在容器货品明细表中找到托盘{task.S_CNTR_CODE}对应的物料"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info($"任务{task.S_CODE}完成,记录出入库存在问题:无法在容器货品明细表中找到托盘{task.S_CNTR_CODE}对应的物料"); |
| | | //return; |
| | | cgDetail = new TN_CG_Detail() ; |
| | | cgDetail.S_ITEM_CODE = "异常"; |
| | |
| | | .Where(r => r.S_TASK_NO == task.S_CODE).First(); |
| | | if (record != null) { |
| | | //needUpdateRecordTable = true; |
| | | info = $"出入库记录表中已经存在任务号{task.S_CODE}"; // 防止测试时反复调用134562导致重复记录 |
| | | LogHelper.Info(info); |
| | | LogHelper.Info($"出入库记录表中已经存在任务号{task.S_CODE}"); // 防止测试时反复调用134562导致重复记录 |
| | | return; |
| | | } |
| | | |
| | |
| | | |
| | | // 数据库操作 |
| | | if (db.Insertable(record).ExecuteCommand() <= 0) { |
| | | info = "插入出入库记录表失败:" + JsonConvert.SerializeObject(record); |
| | | LogHelper.Info(info); |
| | | LogHelper.Info("插入出入库记录表失败:" + JsonConvert.SerializeObject(record)); |
| | | return; |
| | | } |
| | | |
| | | info = "插入出入库记录表成功"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info("插入出入库记录表成功"); |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.InfoEx(ex); |
| | |
| | | |
| | | public static void PickUpReturnErp(TN_Task task) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var info = ""; |
| | | var httpH = new HttpHelper(); |
| | | |
| | | try { |
| | |
| | | .First(); |
| | | |
| | | if (plan == null) { |
| | | info = $"计划单号{task.S_BS_NO}不存在!"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info($"计划单号{task.S_BS_NO}不存在!"); |
| | | } |
| | | |
| | | var cgDetail = db.Queryable<TN_CG_Detail>() |
| | |
| | | .First(); |
| | | |
| | | if (cgDetail == null) { |
| | | info = $"物料编码不存在!"; |
| | | LogHelper.Info(info); |
| | | LogHelper.Info($"物料编码不存在!"); |
| | | } |
| | | |
| | | var model = new OtherModel.PickUpReturnErpInfo { |
| | |
| | | plan.SFSL = model.sfsl; |
| | | plan.HWZT = model.hwzt; |
| | | var success = db.Updateable(plan).UpdateColumns(p => new { p.SFJS, p.SFSL, p.HWZT }).ExecuteCommand() > 0; |
| | | info = "更新出库计划单记录表" + (success ? "成功" : "失败"); |
| | | LogHelper.Info(info); |
| | | LogHelper.Info("更新出库计划单记录表" + (success ? "成功" : "失败")); |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.InfoEx(ex); |
| | |
| | | /// <returns></returns> |
| | | public static Result<bool> CreateInboundTask(string startLocCode, string cntrCode) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var info = ""; |
| | | |
| | | var taskInfo = Settings.GetTaskInfo(ETask.M满托下线入库); |
| | | var taskName = taskInfo.TaskName; |
| | |
| | | .First(); |
| | | |
| | | if (startLoc == null) { |
| | | info = $"没有找到起点货位'{startLocCode}',或不满足要求:未上锁,当前容器数量=0"; |
| | | LogHelper.Info(info); |
| | | return new Result<bool>(false, info); |
| | | return NewResult(false, $"没有找到起点货位'{startLocCode}',或不满足要求:未上锁,当前容器数量=0"); |
| | | } |
| | | |
| | | var locCntrRelOld = db.Queryable<TN_Loc_Container>() |
| | |
| | | .First(); |
| | | |
| | | if (endLoc == null) { |
| | | info = $"没有找到合适的【终点货位】,需要满足要求:未上锁,当前容器数量=0"; |
| | | LogHelper.Info(info); |
| | | return new Result<bool>(false, info); |
| | | return NewResult(false, $"没有找到合适的【终点货位】,需要满足要求:未上锁,当前容器数量=0"); |
| | | } |
| | | |
| | | var cntId = locCntrRel.S_CNTR_CODE; |
| | | var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName); |
| | | |
| | | WCSHelper.LockStartLoc(ref startLoc); // 起点出库锁 |
| | | WCSHelper.LockEndLoc(ref endLoc); // 终点入库锁 |
| | | WCSHelper.LockStartLoc(startLoc); // 起点出库锁 |
| | | WCSHelper.LockEndLoc(endLoc); // 终点入库锁 |
| | | |
| | | using (var tran = db.Ado.UseTran()) { |
| | | if (locCntrRelOld != null) { |
| | | if (db.Deleteable(locCntrRelOld).ExecuteCommand() <= 0 && |
| | | db.Updateable<TN_Location>().SetColumns(l => l.N_CURRENT_NUM == 0).Where(l => l.S_CODE == locCntrRelOld.S_LOC_CODE).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"删除旧货位容器关系表失败:货位编码{locCntrRelOld.S_LOC_CODE},容器编码{locCntrRelOld.S_CNTR_CODE}"; |
| | | LogHelper.Info(info); |
| | | return new Result<bool>(false, info); |
| | | return NewResult(false, $"删除旧货位容器关系表失败:货位编码{locCntrRelOld.S_LOC_CODE},容器编码{locCntrRelOld.S_CNTR_CODE}"); |
| | | } |
| | | } |
| | | |
| | | if (db.Insertable(locCntrRel).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"插入货位容器关系表失败:货位编码{locCntrRel.S_LOC_CODE},容器编码{locCntrRel.S_CNTR_CODE}"; |
| | | LogHelper.Info(info); |
| | | return new Result<bool>(false, info); |
| | | return NewResult(false, $"插入货位容器关系表失败:货位编码{locCntrRel.S_LOC_CODE},容器编码{locCntrRel.S_CNTR_CODE}"); |
| | | } |
| | | |
| | | if (db.Updateable(startLoc).UpdateColumns(it => new { |
| | | it.N_LOCK_STATE, |
| | | it.S_LOCK_STATE, |
| | | it.S_LOCK_OP, |
| | | it.T_MODIFY, |
| | | it.N_CURRENT_NUM, // 起点货位绑定后,将货位状态更新 |
| | | }).ExecuteCommand() <= 0) { |
| | | if (db.Updateable(startLoc).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY, it.N_CURRENT_NUM, }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"生成任务'{taskName}'失败:更新起点货位{startLoc.S_CODE}锁状态失败"; |
| | | LogHelper.Info(info); |
| | | return new Result<bool>(false, info); |
| | | return NewResult(false, $"生成任务'{taskName}'失败:更新起点货位{startLoc.S_CODE}锁状态失败"); |
| | | } |
| | | |
| | | if (db.Updateable(endLoc).UpdateColumns(it => new { |
| | | it.N_LOCK_STATE, |
| | | it.S_LOCK_STATE, |
| | | it.S_LOCK_OP, |
| | | it.T_MODIFY, |
| | | }).ExecuteCommand() <= 0) { |
| | | if (db.Updateable(endLoc).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY, }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"生成任务'{taskName}'失败:更新终点货位{endLoc.S_CODE}锁状态失败"; |
| | | LogHelper.Info(info); |
| | | return new Result<bool>(false, info); |
| | | return NewResult(false, $"生成任务'{taskName}'失败:更新终点货位{endLoc.S_CODE}锁状态失败"); |
| | | } |
| | | |
| | | if (db.Insertable(task).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | info = $"生成任务'{taskName}'失败,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"; |
| | | LogHelper.Info(info); |
| | | return new Result<bool>(false, info); |
| | | return NewResult(false, $"生成任务'{taskName}'失败,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"); |
| | | } |
| | | |
| | | tran.CommitTran(); |
| | | info = $"生成任务'{taskName}'成功,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"; |
| | | LogHelper.Info(info); |
| | | return new Result<bool>(true, info); |
| | | return NewResult(true, $"生成任务'{taskName}'成功,任务号={task.S_CODE},容器号={cntId},起点={startLoc.S_CODE},终点={endLoc.S_CODE}"); |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | |
| | | |
| | | using TcpClient = System.Net.Sockets.TcpClient; |
| | | using System.IO; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.device { |
| | | // 定义Modbus通讯接口 |
| | |
| | | |
| | | using EasyModbus; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.device { |
| | | /// <summary> |
| | | /// modbus tcp 用第三方的包 |
| | |
| | | using Opc.Ua; |
| | | using System; |
| | | using Opc.Ua.Configuration; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.device |
| | |
| | | using System; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | using Newtonsoft.Json.Linq; |
| | | |
| | |
| | | using HH.WCS.Mobox3.DSZSH.api; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json.Linq; |
| | | using S7.Net; |
| | | using S7.Net.Types; |
| | |
| | | using HH.WCS.Mobox3.DSZSH; |
| | | using HH.WCS.Mobox3.DSZSH.device; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.device { |
| | |
| | | using HH.WCS.Mobox3.DSZSH.dispatch; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | using System; |
| | | using System.Collections.Generic; |
| | |
| | | using Newtonsoft.Json; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | |
| | | using SqlSugar; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.models { |
| | | /// <summary> |
| | | /// 【框架】模板抽象类:基本表数据模型 |
| | | /// </summary> |
| | | public abstract class BaseModel { |
| | | |
| | | /// <summary> |
| | | /// 唯一识别码 (底层主键) |
| | | /// </summary> |
| | | [SugarColumn(IsPrimaryKey = true)] |
| | | public string S_ID { get; set; } = Guid.NewGuid().ToString("D"); |
| | | |
| | | /// <summary> |
| | | /// 创建人 ID |
| | | /// </summary> |
| | | public string S_CREATOR_ID { get; set; } = "sa"; |
| | | |
| | | /// <summary> |
| | | /// 创建人名称 |
| | | /// </summary> |
| | | public string S_CREATOR_NAME { get; set; } = "超级用户"; |
| | | |
| | | /// <summary> |
| | | /// 创建时间 |
| | | /// </summary> |
| | | public DateTime T_CREATE { get; set; } = DateTime.Now; |
| | | |
| | | /// <summary> |
| | | /// 修改时间 |
| | | /// </summary> |
| | | public DateTime T_MODIFY { get; set; } = DateTime.Now; |
| | | |
| | | /// <summary> |
| | | /// 数据状态:编辑,定版 |
| | | /// </summary> |
| | | public string S_STATE { get; set; } = "编辑"; |
| | | public string S_STATE { get; set; } = "编辑"; // 编辑;定版 |
| | | } |
| | | } |
| | |
| | | |
| | | public int N_DETAIL_COUNT { get; set; } |
| | | |
| | | #region 非字段部分 |
| | | /// <summary> |
| | | /// <!--默认不使用-->SqlSugar关系映射列表 |
| | | /// </summary> |
| | | [SugarColumn(IsIgnore = true)] |
| | | [Navigate(NavigateType.OneToMany, nameof(TN_CG_Detail.S_CNTR_CODE), nameof(S_CODE))] |
| | | public List<TN_CG_Detail> CntrItemRels { get; set; } |
| | | |
| | | #endregion |
| | | } |
| | | } |
| | |
| | | /// </summary> |
| | | public string S_CNTR_TYPE { get; set; } |
| | | |
| | | |
| | | // 容器-物料 1:n |
| | | #region 非字段部分 |
| | | /// <summary> |
| | | /// <!--默认不使用-->SqlSugar关系映射列表 |
| | | /// </summary> |
| | | [Navigate(NavigateType.OneToMany, nameof(TN_CG_Detail.S_CNTR_CODE))] |
| | | public List<TN_CG_Detail> CntrItemRels { get; set; } |
| | | |
| | | // 容器关系表-容器 1:1 |
| | | /// <summary> |
| | | /// <!--默认不使用-->SqlSugar关系映射列表 |
| | | /// </summary> |
| | | [Navigate(NavigateType.OneToOne, nameof(S_CNTR_CODE))] |
| | | public TN_Container Container { get; set; } |
| | | #endregion |
| | | } |
| | | } |
| | |
| | | using SqlSugar; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.models { |
| | | /// <summary> |
| | | /// 【框架】货位表 |
| | | /// </summary> |
| | | |
| | | [SugarTable("TN_Location")] |
| | | public class TN_Location : BaseModel { |
| | | /// <summary> |
| | | /// 货位 ID |
| | | /// </summary> |
| | | public string S_CODE { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 货位名称 |
| | | /// </summary> |
| | | public string S_NAME { get; set; } = ""; |
| | | |
| | | /// <summary> |
| | | /// 货位所在区域 ID |
| | | /// </summary> |
| | | public string S_AREA_CODE { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 国自 AGV 对应的库位名称 |
| | | /// </summary> |
| | | public string S_AGV_SITE { get; set; } = "0"; |
| | | |
| | | /// <summary> |
| | | /// 货位容器容量 |
| | | /// </summary> |
| | | public int N_CAPACITY { get; set; } = 1; |
| | | |
| | | /// <summary> |
| | | /// 货位当前容器数量 |
| | | /// </summary> |
| | | public int N_CURRENT_NUM { get; set; } = 0; |
| | | |
| | | /// <summary> |
| | | /// 行号 |
| | | /// </summary> |
| | | public int N_ROW { get; set; } = 0; |
| | | |
| | | /// <summary> |
| | | /// 列号 |
| | | /// </summary> |
| | | public int N_COL { get; set; } = 0; |
| | | |
| | | /// <summary> |
| | | /// 货位的层数 |
| | | /// </summary> |
| | | public int N_LAYER { get; set; } = 1; |
| | | |
| | | // BEG 初始化表格使用 |
| | |
| | | /// </summary> |
| | | public string S_LOCK_OP { get; set; } = ""; |
| | | |
| | | /// <summary> |
| | | /// 货位是否启用:Y启用 |
| | | /// </summary> |
| | | public string C_ENABLE { get; set; } = "Y"; |
| | | |
| | | #region 非字段部分 |
| | | /// <summary> |
| | | /// 货位-容器 关系映射 |
| | | /// <!--默认不使用-->SqlSugar关系映射列表 |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// 默认是一对多,通常情况是一对一 |
| | | /// </remarks> |
| | | [Navigate(NavigateType.OneToMany, nameof(TN_Loc_Container.S_LOC_CODE))] |
| | | public List<TN_Loc_Container> LocCntrRels { get; set; } |
| | | |
| | |
| | | } |
| | | return str; |
| | | } |
| | | #endregion |
| | | } |
| | | } |
| | |
| | | ///// </summary> |
| | | //public int N_FORCE { get; set; } = 0; |
| | | |
| | | internal static string GetStateStr(int state) { |
| | | #region 非字段部分 |
| | | public static string GetStateStr(int state) { |
| | | // 0等待 1已推送 2执行 3完成 4错误 |
| | | var status = ""; |
| | | switch (state) { |
| | |
| | | } |
| | | return status; |
| | | } |
| | | #endregion |
| | | } |
| | | } |
| | |
| | | using NLog.Config; |
| | | using NLog.Targets; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH { |
| | | namespace HH.WCS.Mobox3.DSZSH.util { |
| | | public class LogHelper |
| | | { |
| | | public static Dictionary<string, ILogger> loggers = new Dictionary<string, ILogger>(); |
| | |
| | | using Newtonsoft.Json; |
| | | using Newtonsoft.Json.Linq; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH { |
| | | namespace HH.WCS.Mobox3.DSZSH.util { |
| | | public class Settings |
| | | { |
| | | public static string WebApiUrl { get; set; } |
New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.models; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | |
| | | using SqlSugar; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.wms { |
| | | /// <summary> |
| | | /// [ 数据库事务处理 ] 帮助类 |
| | | /// </summary> |
| | | public class DbTranHelper { |
| | | /// <summary> |
| | | /// 数据库事务处理 ( 创建任务 ) |
| | | /// </summary> |
| | | /// <remarks>要求: obj != null</remarks> |
| | | /// <param name="obj"></param> |
| | | /// <returns></returns> |
| | | public static (bool Success, string Message) DoDbTranTask(DbTranTaskObj obj) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | try { |
| | | using (var tran = db.Ado.UseTran()) { |
| | | // 存在[旧]容器关联信息:删除[旧][容器货品明细][货位容器关系],更新[货位][容器数量] |
| | | if (obj.Old != null) { |
| | | if (obj.Old.CgDetail != null && db.Deleteable(obj.Old.CgDetail).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | return (false, $"删除[旧物料信息]失败!!数据:\n\n{JsonConvert.SerializeObject(obj.Old.CgDetail)}\n"); |
| | | } |
| | | if (obj.Old.LocCntrRel != null && db.Deleteable(obj.Old.LocCntrRel).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | return (false, $"删除[旧货位容器关系]失败!!数据:\n\n{JsonConvert.SerializeObject(obj.Old.LocCntrRel)}\n"); |
| | | } |
| | | if (obj.Old.Location != null && db.Updateable(obj.Old.Location).UpdateColumns(l => new { l.N_CURRENT_NUM, l.T_MODIFY }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | return (false, $"更新[旧货位][当前容器数量]失败!!货位='{obj.Old.Location.S_CODE}',数量=>{obj.Old.Location.N_CURRENT_NUM}"); |
| | | } |
| | | } |
| | | |
| | | // 更新[容器表](业务需要) |
| | | if (obj.ContainerToUpdate != null && db.Updateable(obj.ContainerToUpdate).UpdateColumns(c => new { c.S_SPEC, c.S_SOURCE, c.T_MODIFY }).ExecuteCommand() <= 0) { |
| | | return (false, $"更新[容器表]失败!!数据:\n\n{JsonConvert.SerializeObject(obj.ContainerToUpdate)}\n"); |
| | | } |
| | | |
| | | // 更新[容器货品明细](业务需要) |
| | | if (obj.CgDetailToUpdate != null && db.Updateable(obj.CgDetailToUpdate).UpdateColumns(it => new { it.N_ITEM_STATE, it.S_ITEM_STATE, it.T_MODIFY }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | return (false, $"更新[物料明细表]失败!!物料号='{obj.CgDetailToUpdate}',物料状态=>'{obj.CgDetailToUpdate.S_ITEM_STATE}'"); |
| | | } |
| | | |
| | | // 存在[新][货位容器绑定关系]:插入[货位容器关系表] |
| | | if (obj.LocCntrRelToInsert != null && db.Insertable(obj.LocCntrRelToInsert).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | return (false, $"插入[容器货位绑定表]失败!!数据:\n\n{JsonConvert.SerializeObject(obj.LocCntrRelToInsert)}\n"); |
| | | } |
| | | |
| | | // 更新[起点][终点][锁状态],创建[任务] |
| | | if (obj.StartLocToUpdate != null && db.Updateable(obj.StartLocToUpdate).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY, it.N_CURRENT_NUM, }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | return (false, $"更新[起点货位锁状态]失败!!起点='{obj.StartLocToUpdate.S_CODE}',锁状态=>'{obj.StartLocToUpdate.S_LOCK_STATE}'"); |
| | | } |
| | | if (obj.EndLocToUpdate != null && db.Updateable(obj.EndLocToUpdate).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY, }).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | return (false, $"更新[终点货位锁状态]失败!!终点='{obj.EndLocToUpdate.S_CODE}',锁状态=>'{obj.EndLocToUpdate.S_LOCK_STATE}'"); |
| | | } |
| | | if (obj.TaskToInsert != null && db.Insertable(obj.TaskToInsert).ExecuteCommand() <= 0) { |
| | | tran.RollbackTran(); |
| | | return (false, $"生成任务'{obj.TaskToInsert.S_TYPE}'失败!!任务号='{obj.TaskToInsert.S_CODE}',容器号='{obj.TaskToInsert.S_CNTR_CODE}',起点='{obj.TaskToInsert.S_START_LOC}',终点='{obj.TaskToInsert.S_END_LOC}'"); |
| | | } |
| | | |
| | | // 提交数据库更改 |
| | | tran.CommitTran(); |
| | | return (true, $"生成任务'{obj.TaskToInsert.S_TYPE}'成功!!任务号='{obj.TaskToInsert.S_CODE}',容器号='{obj.TaskToInsert.S_CNTR_CODE}',起点='{obj.TaskToInsert.S_START_LOC}',终点='{obj.TaskToInsert.S_END_LOC}'"); |
| | | } |
| | | } |
| | | catch (Exception) { |
| | | throw; // 由外部方法捕获处理 |
| | | } |
| | | } |
| | | } |
| | | |
| | | public class DbTranTaskObj { |
| | | public LocCntrCg Old { get; set; } = null; |
| | | public TN_Container ContainerToUpdate { get; set; } = null; |
| | | public TN_CG_Detail CgDetailToUpdate { get; set; } = null; |
| | | public TN_Loc_Container LocCntrRelToInsert { get; set; } = null; |
| | | public TN_Location StartLocToUpdate { get; set; } = null; |
| | | public TN_Location EndLocToUpdate { get; set; } = null; |
| | | public TN_Task TaskToInsert { get; set; } = null; |
| | | } |
| | | |
| | | } |
| | |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.wms { |
| | | /// <summary> |
| | | /// 序列号生成帮助类 (名称/命名空间为历史遗留问题) |
| | | /// </summary> |
| | | internal class SYSHelper { |
| | | private static object locker = new object(); |
| | | internal static int GetSerialNumber(string snType, string prefix) { |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ![[弃用|理由:不灵活,涉及业务过于具体]]检查容器类型是否正确 |
| | | /// <!--弃用|理由:不灵活,涉及业务过于具体-->检查容器类型是否正确 |
| | | /// </summary> |
| | | /// <param name="cntrCode"></param> |
| | | /// <param name="cntrType"></param> |
| | |
| | | if (locCntrRel != null) { |
| | | location = db.Queryable<TN_Location>().Where(l => l.S_CODE == locCntrRel.S_LOC_CODE).First(); |
| | | if (location == null) { |
| | | LogHelper.Warn($""); |
| | | LogHelper.Warn($"获取容器关联信息:[货位容器关系]存在,但[货位]不存在!容器='{cntrCode}',货位='{locCntrRel.S_LOC_CODE}'"); |
| | | } |
| | | } |
| | | if (location != null) { |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 绑定[货位-容器]信息 |
| | | /// [绑定[货位-容器]信息](设置货位数量为1;不会检查loc是否为null) |
| | | /// </summary> |
| | | /// <param name="startLoc"></param> |
| | | /// <param name="loc"></param> |
| | | /// <param name="cntrCode"></param> |
| | | /// <returns></returns> |
| | | public static TN_Loc_Container BindLocCntr(ref TN_Location startLoc, string cntrCode) { |
| | | public static TN_Loc_Container BindLocCntr(ref TN_Location loc, string cntrCode) { |
| | | var locCntrRel = new TN_Loc_Container { |
| | | S_LOC_CODE = startLoc.S_CODE, |
| | | S_LOC_CODE = loc.S_CODE, |
| | | S_CNTR_CODE = cntrCode, |
| | | }; |
| | | |
| | | startLoc.N_CURRENT_NUM = 1; |
| | | startLoc.T_MODIFY = DateTime.Now; |
| | | if (loc.N_CURRENT_NUM != 0) { |
| | | LogHelper.Warn($"绑定货位容器:程序正在尝试给[容器数量]不是0的货位,设置[容器数量]为1!货位='{loc.S_CODE}',容器数量={loc.N_CURRENT_NUM}"); |
| | | } |
| | | |
| | | loc.N_CURRENT_NUM = 1; |
| | | loc.T_MODIFY = DateTime.Now; |
| | | |
| | | return locCntrRel; |
| | | } |
| | | |
| | | public static TN_Loc_Container BindLocCntrs(ref TN_Location loc, List<string> cntrCodes) { |
| | | var locCntrRel = new TN_Loc_Container { |
| | | S_LOC_CODE = loc.S_CODE, |
| | | S_CNTR_CODE = string.Join(",", cntrCodes) |
| | | }; |
| | | |
| | | if (loc.N_CURRENT_NUM != 0) { |
| | | LogHelper.Warn($"绑定货位容器:程序正在尝试给[容器数量]不是0的货位,设置[容器数量]为1!货位='{loc.S_CODE}',容器数量={loc.N_CURRENT_NUM}"); |
| | | } |
| | | |
| | | loc.N_CURRENT_NUM = 1; |
| | | loc.T_MODIFY = DateTime.Now; |
| | | |
| | | return locCntrRel; |
| | | } |
| | |
| | | /// <summary> |
| | | /// 起点出库锁 |
| | | /// </summary> |
| | | /// <remarks>要求: loc != null; 锁状态='无';</remarks> |
| | | /// <param name="loc"></param> |
| | | /// <param name="lockSource"></param> |
| | | public static void LockStartLoc(ref TN_Location loc, string lockSource = "") { |
| | | if (loc == null) { |
| | | throw new ArgumentNullException(); // 接受货位loc为空时直接抛异常(通常不会发生) |
| | | } |
| | | |
| | | public static void LockStartLoc(TN_Location loc, string lockSource = "") { |
| | | if (loc.N_LOCK_STATE != 0 || loc.S_LOCK_STATE != "无") { |
| | | LogHelper.Warn($"起点出库锁:程序正在尝试给当前[锁状态]不是'无'的货位上锁!货位='{loc.S_CODE}',锁状态=({loc.N_LOCK_STATE},{loc.S_LOCK_STATE})"); |
| | | LogHelper.Warn($"起点出库锁:程序正在尝试给当前[锁状态]≠'无'的货位上锁!货位='{loc.S_CODE}',锁状态=({loc.N_LOCK_STATE},{loc.S_LOCK_STATE})"); |
| | | } |
| | | |
| | | loc.N_LOCK_STATE = 2; // 起点出库锁 |
| | | loc.S_LOCK_STATE = TN_Location.GetLockStateStr(2); // 起点出库锁 |
| | | loc.S_LOCK_OP = lockSource; |
| | | loc.T_MODIFY = System.DateTime.Now; |
| | | |
| | | LogHelper.Info($"起点出库锁:起点货位'{loc.S_CODE}'设置[出库锁]"); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 终点入库锁 |
| | | /// </summary> |
| | | /// <remarks>要求: loc != null; 锁状态='无';</remarks> |
| | | /// <param name="loc"></param> |
| | | /// <param name="lockSource"></param> |
| | | public static void LockEndLoc(ref TN_Location loc, string lockSource = "") { |
| | | if (loc == null) { |
| | | throw new ArgumentNullException(); // 接受货位loc为空时直接抛异常(通常不会发生) |
| | | } |
| | | |
| | | public static void LockEndLoc(TN_Location loc, string lockSource = "") { |
| | | if (loc.N_LOCK_STATE != 0 || loc.S_LOCK_STATE != "无") { |
| | | LogHelper.Warn($"起点出库锁:程序正在尝试给当前[锁状态]不是'无'的货位上锁!货位='{loc.S_CODE}',锁状态=({loc.N_LOCK_STATE},{loc.S_LOCK_STATE})"); |
| | | LogHelper.Warn($"终点入库锁:程序正在尝试给当前[锁状态]≠'无'的货位上锁!货位='{loc.S_CODE}',锁状态=({loc.N_LOCK_STATE},{loc.S_LOCK_STATE})"); |
| | | } |
| | | |
| | | loc.N_LOCK_STATE = 1; // 终点出库锁 |
| | | loc.S_LOCK_STATE = TN_Location.GetLockStateStr(1); // 终点出库锁 |
| | | loc.N_LOCK_STATE = 1; // 终点入库锁 |
| | | loc.S_LOCK_STATE = TN_Location.GetLockStateStr(1); // 终点入库锁 |
| | | loc.S_LOCK_OP = lockSource; |
| | | loc.T_MODIFY = System.DateTime.Now; |
| | | |
| | | LogHelper.Info($"终点入库锁:终点货位='{loc.S_CODE}',来源='{lockSource}'"); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 创建任务 |
| | | /// [创建任务](需确保startLoc/endLoc不为null;不会检查货位S_CODE,S_AREA_CODE属性是否合法) |
| | | /// </summary> |
| | | /// <param name="startLoc">起点货位:至少提供:S_CODE,S_AREA_CODE</param> |
| | | /// <param name="endLoc">终点货位:至少提供:S_CODE,S_AREA_CODE</param> |
| | | /// <param name="cntId">容器号</param> |
| | | /// <param name="type">任务类型(名称)</param> |
| | | /// <param name="pri">优先级</param> |
| | | /// <param name="agvType">AGV类型</param> |
| | | /// <param name="agv">AGV类型</param> |
| | | /// <returns></returns> |
| | | public static TN_Task BuildTask(TN_Location startLoc, TN_Location endLoc, string cntId, string type, int pri = 3, int agvType = 1) { |
| | | public static TN_Task BuildTask(TN_Location startLoc, TN_Location endLoc, string cntId, string type, int pri = 3, int agv = 1) { |
| | | TN_Task TN_Task = new TN_Task() { |
| | | S_CODE = GenerateTaskNo(), |
| | | S_START_AREA = startLoc.S_AREA_CODE, |
| | | S_END_AREA = endLoc.S_AREA_CODE, |
| | | S_START_LOC = startLoc.S_CODE, |
| | | S_END_LOC = endLoc.S_CODE, |
| | | S_CNTR_CODE = cntId, |
| | | S_TYPE = type, |
| | | N_PRIORITY = pri, |
| | | N_SCHEDULE_TYPE = agvType, |
| | | N_SCHEDULE_TYPE = agv, |
| | | N_B_STATE = 0, // 任务创建时,默认等待 |
| | | S_CNTR_CODE = cntId, |
| | | }; |
| | | |
| | | LogHelper.Info($"创建任务:任务号='{TN_Task.S_CODE}'"); |
| | | |
| | | return TN_Task; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// [ 创建任务,并上锁 ] ( 需确保startLoc/endLoc不为null ; 不会检查货位S_CODE,S_AREA_CODE属性是否合法 ) |
| | | /// </summary> |
| | | /// <remarks>要求 : (1) startLoc / endLoc ≠ null<br/>(2) startLoc / endLoc 存在 S_CODE , S_AREA_CODE</remarks> |
| | | /// <param name="startLoc">起点货位 : 至少提供 : S_CODE , S_AREA_CODE</param> |
| | | /// <param name="endLoc">终点货位 : 至少提供 : S_CODE , S_AREA_CODE</param> |
| | | /// <param name="cntId">容器号</param> |
| | | /// <param name="type">任务类型(名称)</param> |
| | | /// <param name="pri">优先级</param> |
| | | /// <param name="agv">AGV类型</param> |
| | | /// <returns></returns> |
| | | public static TN_Task BuildTaskWithLocLock(TN_Location startLoc, TN_Location endLoc, string cntId, string type, int pri = 3, int agv = 1) { |
| | | TN_Task TN_Task = new TN_Task() { |
| | | S_CODE = GenerateTaskNo(), |
| | | S_START_AREA = startLoc.S_AREA_CODE, |
| | | S_END_AREA = endLoc.S_AREA_CODE, |
| | | S_START_LOC = startLoc.S_CODE, |
| | | S_END_LOC = endLoc.S_CODE, |
| | | S_CNTR_CODE = cntId, |
| | | S_TYPE = type, |
| | | N_PRIORITY = pri, |
| | | N_SCHEDULE_TYPE = agv, |
| | | N_B_STATE = 0, // 任务创建时,默认等待 |
| | | }; |
| | | |
| | | LogHelper.Info($"创建任务:任务号='{TN_Task.S_CODE}'"); |
| | | |
| | | LockStartLoc(startLoc, TN_Task.S_CODE); |
| | | LockEndLoc(endLoc, TN_Task.S_CODE); |
| | | |
| | | return TN_Task; |
| | | } |
| | | |
| | | internal static bool CheckActionRecordExist(string no, int code) { |
| | | var db = new SqlHelper<TN_Task_Action>().GetInstance(); |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Security.Cryptography; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | |
| | | using HH.WCS.Mobox3.DSZSH.models; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | |
| | | using Newtonsoft.Json; |
| | | |
| | | using static HH.WCS.Mobox3.DSZSH.api.ApiModel; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.wms { |
| | | public class WMSHelper { |
| | | |