优化WCSHelper / 序列号生成逻辑 , 添加强制任务处理模块
| | |
| | | private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>(); |
| | | private readonly string _xmlPath; |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <summary></summary> |
| | | /// <param name="swaggerProvider"></param> |
| | | /// <param name="xmlpath">xml文档路径</param> |
| | | public SwaggerCacheProvider(ISwaggerProvider swaggerProvider, string xmlpath) |
| | |
| | | { |
| | | srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion); |
| | | |
| | | srcDoc.vendorExtensions = new Dictionary<string, object> |
| | | { |
| | | srcDoc.vendorExtensions = new Dictionary<string, object> { |
| | | { "ControllerDesc", GetControllerDesc() } |
| | | }; |
| | | _cache.TryAdd(cacheKey, srcDoc); |
| | |
| | | <Compile Include="api\ApiModel.cs" /> |
| | | <Compile Include="api\DebugController.cs" /> |
| | | <Compile Include="api\ErpController.cs" /> |
| | | <Compile Include="api\ForceController.cs" /> |
| | | <Compile Include="api\MesController.cs" /> |
| | | <Compile Include="api\MoboxController.cs" /> |
| | | <Compile Include="api\AgvController.cs" /> |
| | |
| | | <Compile Include="util\LogHelper.cs" /> |
| | | <Compile Include="util\WebHelper.cs" /> |
| | | <Compile Include="wms\DbTran.cs" /> |
| | | <Compile Include="wms\LocationHelper.cs" /> |
| | | <Compile Include="wms\LogMsg.cs" /> |
| | | <Compile Include="wms\DbExpr.cs" /> |
| | | <Compile Include="wms\SYSHelper.cs" /> |
| | |
| | | } |
| | | catch (Exception ex) { |
| | | return NewSimpleResult(ex, preLog); |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, model.CntId, taskInfo.TaskName); |
| | | |
| | | if (needUpdateContainer) { |
| | | cntr.S_SOURCE = task.S_CODE; // 用任务号作为容器更新的依据 |
| | | cntr.T_MODIFY = DateTime.Now; |
| | | } |
| | | else { |
| | | cntr = null; |
| | | } |
| | | |
| | | (ok, msg) = DbTran.CreateTask(new CreateTaskObj { |
| | | ContainerToUpdate = cntr, |
| | | ContainerToUpdate = needUpdateContainer ? cntr : null, |
| | | StartLocToUpdate = startLoc, |
| | | EndLocToUpdate = endLoc, |
| | | TaskToInsert = task, |
| | |
| | | } |
| | | |
| | | private static string GenerateOrderNo(string snType, string prefix) { |
| | | var id = SYSHelper.GetSerialNumber(snType, prefix); |
| | | var date = DateTime.Now.ToString("yyMMdd"); |
| | | return $"{prefix}{date}-{id.ToString().PadLeft(4, '0')}"; |
| | | //var id = SYSHelper.GetSerialNumberResetByDay(snType, prefix); |
| | | //var date = DateTime.Now.ToString("yyMMdd"); |
| | | //return $"{prefix}{date}-{id.ToString().PadLeft(4, '0')}"; |
| | | return SYSHelper.GenerateSN(snType, prefix, "yyMMdd"); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | |
| | | return ex.Message; |
| | | } |
| | | } |
New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using System.Web.Http; |
| | | using HH.WCS.Mobox3.DSZSH.models; |
| | | using HH.WCS.Mobox3.DSZSH.util; |
| | | using HH.WCS.Mobox3.DSZSH.wms; |
| | | |
| | | using static HH.WCS.Mobox3.DSZSH.api.ApiModel; |
| | | using static HH.WCS.Mobox3.DSZSH.util.Config; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.api { |
| | | /// <summary> |
| | | /// 应急/特殊情况的强制操作流程 |
| | | /// </summary> |
| | | [RoutePrefix("force")] |
| | | public class ForceController : ApiController { |
| | | /// <summary> |
| | | /// 强制创建任务并下发 |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | [HttpPost] |
| | | [Route("ForceInbound")] |
| | | public SimpleResult ForceCreateTask(ForceModel.ForceCreateTaskInfo model) { |
| | | return ForceService.ForceCreateTask(model); |
| | | } |
| | | |
| | | public SimpleResult ForceAddCgDetail() { |
| | | return NewSimpleResult(0, ""); |
| | | } |
| | | } |
| | | |
| | | public class ForceService { |
| | | public static SimpleResult ForceCreateTask(ForceModel.ForceCreateTaskInfo model) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var (ok, msg) = (false, string.Empty); |
| | | var taskInfo = ETask.M满箱下线入库.Info(); |
| | | const string preLog = "DEBUG:强制创建任务:"; |
| | | |
| | | try { |
| | | var startLoc = db.Queryable<TN_Location>().Where(DbExpr.StartLocUnbind(model.StartLoc, taskInfo.StartAreas)).First(); |
| | | if (startLoc == null) { |
| | | return NewSimpleResult(2, preLog + LogMsg.StartLocUnbindNotFound(model.StartLoc, taskInfo.StartAreas)); |
| | | } |
| | | |
| | | var endLoc = db.Queryable<TN_Location>().Where(DbExpr.EndLoc(areas: taskInfo.EndAreas)) |
| | | .OrderBy(l => new { l.N_LAYER }).First(); |
| | | if (endLoc == null) { |
| | | return NewSimpleResult(3, preLog + LogMsg.EndLocNotFound(areas: taskInfo.EndAreas)); |
| | | } |
| | | |
| | | var task = WCSHelper.BuildTaskWithLocLock(startLoc, endLoc, model.CntId, taskInfo.TaskName); |
| | | |
| | | (ok, msg) = DbTran.CreateTask(new CreateTaskObj { |
| | | StartLocToUpdate = startLoc, |
| | | EndLocToUpdate = endLoc, |
| | | TaskToInsert = task, |
| | | }); |
| | | return NewSimpleResult(ok ? 0 : 500, preLog + msg); |
| | | } |
| | | catch (Exception ex) { |
| | | return NewSimpleResult(ex, preLog); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public class ForceModel { |
| | | public class ForceCreateTaskInfo { |
| | | public string StartLoc { get; set; } |
| | | public string EndLoc { get; set; } |
| | | public string CntId { get; set; } // 可为空 |
| | | } |
| | | } |
| | | } |
| | |
| | | WCSHelper.Begin(TN_Task, model.forklift_no); // 已推送的任务的状态改成执行 |
| | | break; |
| | | case 3: // 开始取货 |
| | | WCSHelper.UpdateStatus(TN_Task, "开始取货"); // 任务状态改成开始取货 |
| | | WCSHelper.UpdateTaskState(TN_Task, "开始取货"); // 任务状态改成开始取货 |
| | | break; |
| | | case 4: // 取货完成 |
| | | WCSHelper.UpdateStatus(TN_Task, "取货完成"); // 任务状态改成取货完成 |
| | | WCSHelper.UpdateTaskState(TN_Task, "取货完成"); // 任务状态改成取货完成 |
| | | TaskProcess.OperateStatus(TN_Task, 4); // 起点容器货位解绑,解锁起点 |
| | | |
| | | if (TN_Task.S_TYPE == ETask.C成品胶出库.Name()) { |
| | |
| | | |
| | | break; |
| | | case 5: // 开始卸货 |
| | | WCSHelper.UpdateStatus(TN_Task, "开始卸货"); // 任务状态改成开始卸货 |
| | | WCSHelper.UpdateTaskState(TN_Task, "开始卸货"); // 任务状态改成开始卸货 |
| | | break; |
| | | case 6: // 卸货完成 |
| | | WCSHelper.UpdateStatus(TN_Task, "卸货完成"); // 任务状态改成卸货完成 |
| | | WCSHelper.UpdateTaskState(TN_Task, "卸货完成"); // 任务状态改成卸货完成 |
| | | TaskProcess.OperateStatus(TN_Task, 6); // 终点容器货位绑定,解锁终点 |
| | | break; |
| | | case 2: // 完成 |
| | |
| | | var taskType = mst.S_TYPE.Trim(); |
| | | |
| | | if (mst.N_B_STATE == 0) { |
| | | start = LocationHelper.GetAgvSite(mst.S_START_LOC); |
| | | end = LocationHelper.GetAgvSite(mst.S_END_LOC); |
| | | start = WCSHelper.GetAgvSite(mst.S_START_LOC); |
| | | end = WCSHelper.GetAgvSite(mst.S_END_LOC); |
| | | LogHelper.Info($"NDC推送任务:{mst.S_CODE};start='{start}',end='{end}'"); |
| | | |
| | | var startLoc = LocationHelper.GetLoc(mst.S_START_LOC); |
| | | var endLoc = LocationHelper.GetLoc(mst.S_END_LOC); |
| | | var startLoc = WCSHelper.GetLocation(mst.S_START_LOC); |
| | | var endLoc = WCSHelper.GetLocation(mst.S_END_LOC); |
| | | var dic = new List<param>(); |
| | | dic.Add(new param() { name = "IKey", value = "IKey" }); |
| | | dic.Add(new param() { name = "From", value = start.ToString() }); |
| | |
| | | //推送成功,修改任务优先级 |
| | | mst.N_B_STATE = 1; |
| | | mst.S_B_STATE = TN_Task.GetStateStr(1); |
| | | WCSHelper.UpdateStatus(mst);//更新任务状态 |
| | | WCSHelper.UpdateTaskState(mst);//更新任务状态 |
| | | result = true; |
| | | LogHelper.Info($"NDC推送任务成功:{mst.S_CODE};start='{mst.S_START_LOC}',end='{mst.S_END_LOC}'"); |
| | | } |
| | |
| | | |
| | | if (mst.N_B_STATE == 0) { |
| | | //var code = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, JsonConvert.SerializeObject(new { src = mst.S_START_LOC, dst = mst.S_END_LOC }), "p2p"); |
| | | start = LocationHelper.GetAgvSite(mst.S_START_LOC); |
| | | end = LocationHelper.GetAgvSite(mst.S_END_LOC); |
| | | start = WCSHelper.GetAgvSite(mst.S_START_LOC); |
| | | end = WCSHelper.GetAgvSite(mst.S_END_LOC); |
| | | |
| | | var code = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, JsonConvert.SerializeObject(new { src = start, dst = end }), "p2pdst", "pgapi"); |
| | | |
| | |
| | | mst.N_B_STATE = 1; |
| | | mst.S_B_STATE = TN_Task.GetStateStr(1); |
| | | mst.S_EQ_TASK_CODE = code.ToString(); |
| | | WCSHelper.UpdateStatus(mst); |
| | | WCSHelper.UpdateEQNo(mst); |
| | | WCSHelper.UpdateTaskState(mst); |
| | | WCSHelper.UpdateEqTaskNo(mst); |
| | | LogHelper.Info($"国自推送任务成功 {mst.S_CODE};" + "start=" + mst.S_START_LOC + "end= " + mst.S_END_LOC); |
| | | } |
| | | else { |
| | |
| | | }; |
| | | if (HanAo.CreateOrder(model)) { |
| | | mst.N_B_STATE = 1; |
| | | WCSHelper.UpdateStatus(mst); |
| | | WCSHelper.UpdateTaskState(mst); |
| | | LogHelper.Info($"杭奥推送任务成功 {mst.S_CODE};" + "start=" + model.frmPos + "end= " + model.toPos); |
| | | return true; |
| | | } |
| | |
| | | using NLog.Targets; |
| | | |
| | | namespace HH.WCS.Mobox3.DSZSH.util { |
| | | public class LogHelper |
| | | { |
| | | public class LogHelper { |
| | | public static Dictionary<string, ILogger> loggers = new Dictionary<string, ILogger>(); |
| | | |
| | | #region 初始方法 |
| | | #region 初始方法 ( Error 默认不使用 ) |
| | | public static void Debug(string message, string name = "") { |
| | | ILogger logger = null; |
| | | if (loggers.Keys.Contains(name)) { |
| | |
| | | #endregion |
| | | } |
| | | |
| | | internal class LogFactory |
| | | { |
| | | internal class LogFactory { |
| | | /// <summary> |
| | | /// 通过配置文件配置日志 |
| | | /// </summary> |
| | |
| | | /// 数据库事务处理 ( 创建任务 ) |
| | | /// </summary> |
| | | /// <remarks><b>[ 要求 ]</b> obj ≠ null<br/> |
| | | /// <b>[ 注意 ]</b> 所有的数据库操作 , 都会在对象 = null 时选择跳过 , 且不会报错 , 除了 TaskToInsert ; |
| | | /// <b>[ 注意 ]</b> 所有的数据库操作 , 都会在对象 = null 时选择跳过 , 且不会报错 ( 除了 TaskToInsert ) |
| | | /// <br/>如果存在某个必须完成的数据库操作 , 需在调用时确保该对象 ≠ null</remarks> |
| | | /// <param name="obj"></param> |
| | | /// <returns></returns> |
| | |
| | | /// <summary> |
| | | /// [ 序列号生成 ] 帮助类 |
| | | /// </summary> |
| | | internal class SYSHelper { |
| | | public class SYSHelper { |
| | | private static object locker = new object(); |
| | | internal static int GetSerialNumber(string snType, string prefix) { |
| | | /// <summary> |
| | | /// <c>"{prefix}-{DateTime.Now.ToString(dateFormat)}-{id.ToString().PadLeft(length, '0')}"</c> |
| | | /// </summary> |
| | | /// <param name="snType"></param> |
| | | /// <param name="prefix"></param> |
| | | /// <param name="dateFormat"></param> |
| | | /// <param name="length"></param> |
| | | /// <returns></returns> |
| | | public static string GenerateSN(string snType, string prefix, string dateFormat = "yyMM", int length = 4) { |
| | | var header = $"{prefix}{DateTime.Now.ToString(dateFormat)}-"; |
| | | var res = GetSerialNumber(snType, header); |
| | | if (res == 0) return ""; |
| | | else { |
| | | return $"{header}{res.ToString().PadLeft(length, '0')}"; |
| | | } |
| | | } |
| | | |
| | | private static int GetSerialNumber(string snType, string prefix) { |
| | | int result = 0; |
| | | lock (locker) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var sId = db.Queryable<OI_SYS_MAXID>().Where(a => a.CN_S_TYPE.Trim() == snType && a.CN_S_PRE.Trim() == prefix).First(); |
| | | if (sId != null) { |
| | | |
| | | if (sId.CN_T_LAST < DateTime.Today) { |
| | | sId.CN_N_MAX = 1; |
| | | } |
| | | else { |
| | | sId.CN_N_MAX++; |
| | | } |
| | | |
| | | sId.CN_T_LAST = DateTime.Now; |
| | | if (db.Ado.ExecuteCommand($"update OI_SYS_MAXID set CN_N_MAX={sId.CN_N_MAX}, CN_T_LAST='{sId.CN_T_LAST}' where CN_S_TYPE='{snType}' and CN_S_PRE='{prefix}' ") > 0) { |
| | | if (db.Ado.ExecuteCommand($"update OI_SYS_MAXID set CN_N_MAX={sId.CN_N_MAX} " + |
| | | $"where CN_S_TYPE='{snType}' and CN_S_PRE='{prefix}' ") > 0) { |
| | | result = sId.CN_N_MAX; |
| | | } |
| | | } |
| | |
| | | //插入表 |
| | | sId = new OI_SYS_MAXID { CN_S_TYPE = snType, CN_S_PRE = prefix, CN_N_MAX = 1 }; |
| | | result = db.Insertable(sId).ExecuteCommand() > 0 ? 1 : 0; |
| | | |
| | | } |
| | | } |
| | | return result; |
| | |
| | | /// <summary> |
| | | /// [ 通用业务 ] 帮助类 |
| | | /// </summary> |
| | | internal class WCSHelper { |
| | | internal static string GenerateTaskNo() { |
| | | var id = SYSHelper.GetSerialNumber("任务号", "TN"); |
| | | var date = DateTime.Now.ToString("yyMMdd"); |
| | | return $"TN{date}{id.ToString().PadLeft(4, '0')}"; |
| | | public class WCSHelper { |
| | | #region LocationHelper |
| | | private static Dictionary<string, TN_Location> _locationDict = null; |
| | | |
| | | static WCSHelper() { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | |
| | | try { |
| | | //初始化Location加入到字典缓存 |
| | | _locationDict = new Dictionary<string, TN_Location>(); |
| | | var locList = db.Queryable<TN_Location>().ToList(); |
| | | foreach (var loc in locList) { |
| | | if (!_locationDict.ContainsKey(loc.S_CODE)) { |
| | | _locationDict.Add(loc.S_CODE, loc); |
| | | } |
| | | internal static bool UpdateStatus(TN_Task task, string status) { |
| | | } |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.InfoEx(ex, "WCSHelper:初始化Location到字典缓存"); |
| | | } |
| | | } |
| | | |
| | | public static TN_Location GetLocation(string locCode, bool useDict = true) { |
| | | if (useDict && _locationDict.Keys.Contains(locCode)) { |
| | | return _locationDict[locCode.Trim()]; |
| | | } |
| | | |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<TN_Location>().Where(l => l.S_CODE == locCode).First(); |
| | | } |
| | | |
| | | public static string GetAgvSite(string locCode, bool useDict = true) { |
| | | if (useDict && _locationDict.Keys.Contains(locCode)) { |
| | | return _locationDict[locCode.Trim()].S_AGV_SITE; |
| | | } |
| | | |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var loc = db.Queryable<TN_Location>().Where(l => l.S_CODE == locCode).First(); |
| | | return loc == null ? "0" : loc.S_AGV_SITE; |
| | | } |
| | | #endregion |
| | | |
| | | #region 任务创建 / 下发 / 查询 |
| | | internal static string GenerateTaskNo() { |
| | | //var id = SYSHelper.GetSerialNumberResetByDay("任务号", "TN"); |
| | | //var date = DateTime.Now.ToString("yyMMdd"); |
| | | //return $"TN{date}{id.ToString().PadLeft(4, '0')}"; |
| | | return SYSHelper.GenerateSN("任务号", "TN", "yyMMdd"); |
| | | } |
| | | |
| | | internal static bool UpdateTaskState(TN_Task task, string state) { |
| | | var res = false; |
| | | var db = new SqlHelper<TN_Task>().GetInstance(); |
| | | task.S_B_STATE = status; |
| | | task.S_B_STATE = state; |
| | | res = db.Updateable(task).UpdateColumns(it => new { it.S_B_STATE }).ExecuteCommand() > 0; |
| | | return res; |
| | | } |
| | | internal static bool UpdateStatus(TN_Task task) { |
| | | |
| | | internal static bool UpdateTaskState(TN_Task task) { |
| | | var res = false; |
| | | var db = new SqlHelper<TN_Task>().GetInstance(); |
| | | task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE); |
| | |
| | | res = db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_MODIFY }).ExecuteCommand() > 0; |
| | | return res; |
| | | } |
| | | internal static bool UpdateEQNo(TN_Task task) { |
| | | |
| | | internal static bool UpdateEqTaskNo(TN_Task task) { |
| | | var res = false; |
| | | var db = new SqlHelper<TN_Task>().GetInstance(); |
| | | task.T_MODIFY = DateTime.Now; |
| | | db.Updateable(task).UpdateColumns(it => new { it.S_EQ_TASK_CODE, it.T_MODIFY }).ExecuteCommand(); |
| | | res = db.Updateable(task).UpdateColumns(it => new { it.S_EQ_TASK_CODE, it.T_MODIFY }).ExecuteCommand() > 0; |
| | | return res; |
| | | } |
| | | |
| | | internal static TN_Task GetTask(string no) { |
| | | internal static TN_Task GetTask(string taskNo) { |
| | | var db = new SqlHelper<TN_Task>().GetInstance(); |
| | | var task = db.Queryable<TN_Task>().Where(a => a.S_CODE == no).First(); |
| | | var task = db.Queryable<TN_Task>().Where(a => a.S_CODE == taskNo).First(); |
| | | return task; |
| | | } |
| | | |
| | | public static string GetAgvSite(string locCode) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var loc = db.Queryable<TN_Location>().Where(l => l.S_CODE == locCode).First(); |
| | | return loc == null ? "0" : loc.S_AGV_SITE; |
| | | } |
| | | #endregion |
| | | |
| | | #region 容器相关信息 查询 / 绑定 |
| | | /// <summary> |
| | |
| | | /// <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) { |
| | | public static TN_Task BuildTaskWithLocLock(TN_Location startLoc, TN_Location endLoc, string cntId, string type, |
| | | int pri = 3, int agv = 1) { |
| | | var task = BuildTask(startLoc, endLoc, cntId, type, pri); |
| | | LockStartLoc(startLoc, task.S_CODE); |
| | | LockEndLoc(endLoc, task.S_CODE); |
| | |
| | | } |
| | | #endregion |
| | | |
| | | #region 任务分发 / 执行 / 记录 |
| | | internal static bool CheckActionRecordExist(string no, int code) { |
| | | var db = new SqlHelper<TN_Task_Action>().GetInstance(); |
| | | return db.Queryable<TN_Task_Action>().Count(a => a.S_TASK_CODE == no && a.N_ACTION_CODE == code) > 0; |
| | |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<TN_Task>().Where(a => a.N_B_STATE == 0 && (a.S_B_STATE == "等待" || a.S_B_STATE == "待推送")).ToList(); |
| | | } |
| | | #endregion |
| | | } |
| | | |
| | | /// <summary> |