.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/7725d916-1bef-44d2-8384-bfd94e8b6457.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/e39d6e75-9277-46f5-bff4-9390c52a26f9.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/e9728df6-3b77-4640-883e-78a872e2fb53.vsidxBinary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/f2527103-d3d3-44d1-9a80-1e26bb5cf98f.vsidxBinary files differ
AppStart/SwaggerControllerDescProvider.cs
File was deleted App_Start/Config.cs
App_Start/Settings.cs
App_Start/Startup.cs
File was renamed from AppStart/Startup.cs @@ -4,6 +4,8 @@ using System.Threading.Tasks; using System.Web.Http; using Microsoft.Owin; using Newtonsoft.Json; using Owin; using Swashbuckle.Application; @@ -20,6 +22,8 @@ defaults: new { id = RouteParameter.Optional } ); //SwaggerConfig.Register(config); // Web API routes //config.MapHttpAttributeRoutes(); App_Start/SwaggerConfig.cs
File was renamed from AppStart/SwaggerConfig.cs @@ -1,14 +1,49 @@ using System.Web.Http; using WebActivatorEx; using HH.WCS.Mobox3.Template; using HH.WCS.Mobox3.DSZSH; using Swashbuckle.Application; using System.IO; using System.Reflection; using System; using Swashbuckle.Examples; [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")] namespace HH.WCS.Mobox3.Template namespace HH.WCS.Mobox3.DSZSH { public class SwaggerConfig { public static void Register(HttpConfiguration config) { var thisAssembly = typeof(SwaggerConfig).Assembly; config .EnableSwagger(c => { c.SingleApiVersion("v1", "HH.WCS.Mobox3.DSZSH"); // 设置 XML 注释路径 var baseDirectory = AppDomain.CurrentDomain.BaseDirectory; //var commentsFileName = Assembly.GetExecutingAssembly().GetName().Name + ".xml"; var commentsFileName = "bin\\Debug\\HH.WCS.Mobox3.DSZSH.xml"; var commentsFile = Path.Combine(baseDirectory, commentsFileName); if (File.Exists(commentsFile)) { c.IncludeXmlComments(commentsFile); } // 其他配置... c.UseFullTypeNameInSchemaIds(); // 启用示例数据 //c.DescribeAllEnumsAsStrings(); //c.OperationFilter<ExamplesOperationFilter>(); //c.ModelFilter<ExamplesModelFilter>(); }) .EnableSwaggerUi(c => { // UI 配置 }); } public static void Register() { var thisAssembly = typeof(SwaggerConfig).Assembly; @@ -32,7 +67,7 @@ // hold additional metadata for an API. Version and title are required but you can also provide // additional fields by chaining methods off SingleApiVersion. // c.SingleApiVersion("v1", "HH.WCS.Mobox3.Template"); c.SingleApiVersion("v1", "HH.WCS.Mobox3.DSZSH"); // If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option. // @@ -61,7 +96,7 @@ //c.BasicAuth("basic") // .Description("Basic HTTP Authentication"); // // NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section // NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section //c.ApiKey("apiKey") // .Description("API Key Authentication") // .Name("apiKey") @@ -103,6 +138,10 @@ // //c.IncludeXmlComments(GetXmlCommentsPath()); // 启用 XML 注释 var xmlFile = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\HH.WCS.Mobox3.DSZSH.xml"; c.IncludeXmlComments(xmlFile); // Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types // exposed in your API. However, there may be occasions when more control of the output is needed. // This is supported through the "MapType" and "SchemaFilter" options: App_Start/SwaggerControllerDescProvider.cs
New file @@ -0,0 +1,237 @@ using Swashbuckle.Swagger; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; namespace HH.WCS.Mobox3.DSZSH { /// <summary> /// Swagger 显示控制器的描述 /// </summary> public class SwaggerCacheProvider : ISwaggerProvider { private readonly ISwaggerProvider _swaggerProvider; private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>(); private readonly string _xmlPath; /// <summary> /// /// </summary> /// <param name="swaggerProvider"></param> /// <param name="xmlpath">xml文档路径</param> public SwaggerCacheProvider(ISwaggerProvider swaggerProvider, string xmlpath) { _swaggerProvider = swaggerProvider; _xmlPath = xmlpath; } public SwaggerDocument GetSwagger(string rootUrl, string apiVersion) { var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion); // 只读取一次 if (!_cache.TryGetValue(cacheKey, out SwaggerDocument srcDoc)) { srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion); srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } }; _cache.TryAdd(cacheKey, srcDoc); } return srcDoc; } /// <summary> /// 从API文档中读取控制器描述 /// </summary> /// <returns>所有控制器描述</returns> public ConcurrentDictionary<string, string> GetControllerDesc() { ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>(); if (File.Exists(_xmlPath)) { XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(_xmlPath); string[] arrPath; int cCount = "Controller".Length; foreach (XmlNode node in xmldoc.SelectNodes("//member")) { string type = node.Attributes["name"].Value; if (type.StartsWith("T:")) { arrPath = type.Split('.'); string controllerName = arrPath[arrPath.Length - 1]; if (controllerName.EndsWith("Controller")) // 控制器 { // 获取控制器注释 XmlNode summaryNode = node.SelectSingleNode("summary"); string key = controllerName.Remove(controllerName.Length - cCount, cCount); if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key)) { controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim()); } } } } } return controllerDescDict; } } /// <summary> /// 增强版Swagger提供程序,支持显示控制器和模型的完整文档注释 /// </summary> public class EnhancedSwaggerCacheProvider : ISwaggerProvider { private readonly ISwaggerProvider _swaggerProvider; private static readonly ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>(); private readonly string _xmlPath; public EnhancedSwaggerCacheProvider(ISwaggerProvider swaggerProvider, string xmlpath) { _swaggerProvider = swaggerProvider; _xmlPath = xmlpath; } public SwaggerDocument GetSwagger(string rootUrl, string apiVersion) { var cacheKey = $"{rootUrl}_{apiVersion}"; return _cache.GetOrAdd(cacheKey, _ => { var srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion); // 添加控制器描述 var (controllerDesc, modelDesc) = GetXmlComments(); srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", controllerDesc }, { "ModelDesc", modelDesc } }; // 为模型添加描述 EnhanceModelDescriptions(srcDoc, modelDesc); return srcDoc; }); } /// <summary> /// 从XML文档中提取控制器和模型描述 /// </summary> private (ConcurrentDictionary<string, string> controllerDesc, ConcurrentDictionary<string, string> modelDesc) GetXmlComments() { var controllerDesc = new ConcurrentDictionary<string, string>(); var modelDesc = new ConcurrentDictionary<string, string>(); if (!File.Exists(_xmlPath)) return (controllerDesc, modelDesc); var xmldoc = new XmlDocument(); xmldoc.Load(_xmlPath); foreach (XmlNode node in xmldoc.SelectNodes("//member")) { var type = node.Attributes?["name"]?.Value; if (string.IsNullOrEmpty(type)) continue; if (type.StartsWith("T:")) { var arrPath = type.Split('.'); var typeName = arrPath[arrPath.Length - 1]; // 获取最后一部分 // 处理控制器 if (typeName.EndsWith("Controller")) { var summaryNode = node.SelectSingleNode("summary"); if (summaryNode != null && !string.IsNullOrWhiteSpace(summaryNode.InnerText)) { //var key = typeName[..^"Controller".Length]; string key = typeName; const string controllerSuffix = "Controller"; if (typeName.EndsWith(controllerSuffix)) { key = typeName.Substring(0, typeName.Length - controllerSuffix.Length); } controllerDesc.TryAdd(key, summaryNode.InnerText.Trim()); } } // 处理模型类 else if (IsModelType(node)) { var summaryNode = node.SelectSingleNode("summary"); if (summaryNode != null && !string.IsNullOrWhiteSpace(summaryNode.InnerText)) { modelDesc.TryAdd(typeName, summaryNode.InnerText.Trim()); } // 处理模型属性 EnhancePropertyDescriptions(node, modelDesc); } } } return (controllerDesc, modelDesc); } /// <summary> /// 判断是否为模型类型 /// </summary> private bool IsModelType(XmlNode node) { // 这里可以根据实际需求调整判断逻辑 // 例如:排除Controller、排除特定命名空间等 var type = node.Attributes?["name"]?.Value ?? ""; return type.StartsWith("T:") && !type.EndsWith("Controller") && !type.Contains(".Controllers.") && !type.Contains(".Infrastructure."); } /// <summary> /// 增强模型属性的描述 /// </summary> private void EnhancePropertyDescriptions(XmlNode typeNode, ConcurrentDictionary<string, string> modelDesc) { var typeName = typeNode.Attributes?["name"]?.Value?.Split('.')?.LastOrDefault()?.Substring(2); if (string.IsNullOrEmpty(typeName)) return; foreach (XmlNode propNode in typeNode.SelectNodes("field|property")) { var propName = propNode.Attributes?["name"]?.Value; if (string.IsNullOrEmpty(propName)) continue; var summaryNode = propNode.SelectSingleNode("summary"); var exampleNode = propNode.SelectSingleNode("example"); if (summaryNode != null && !string.IsNullOrWhiteSpace(summaryNode.InnerText)) { var fullPropKey = $"{typeName}.{propName}"; var description = summaryNode.InnerText.Trim(); if (exampleNode != null && !string.IsNullOrWhiteSpace(exampleNode.InnerText)) { description += $"\n\n示例: {exampleNode.InnerText.Trim()}"; } modelDesc.TryAdd(fullPropKey, description); } } } /// <summary> /// 增强Swagger文档中的模型描述 /// </summary> private void EnhanceModelDescriptions(SwaggerDocument swaggerDoc, ConcurrentDictionary<string, string> modelDesc) { if (swaggerDoc.definitions == null) return; foreach (var definition in swaggerDoc.definitions) { // 处理模型类本身描述 if (modelDesc.TryGetValue(definition.Key, out var classDesc)) { definition.Value.description = classDesc; } // 处理模型属性描述 if (definition.Value.properties != null) { foreach (var property in definition.Value.properties) { var fullPropKey = $"{definition.Key}.{property.Key}"; if (modelDesc.TryGetValue(fullPropKey, out var propDesc)) { property.Value.description = propDesc; } } } } } } } Consts/TaskName.cs
@@ -18,5 +18,8 @@ public const string 抽检_不合格移库 = "抽检-不合格移库"; public const string 抽检_出库 = "抽检-出库"; public const string 抽检_合格回库 = "抽检-合格回库"; public const string 移库 = "移库"; public const string 尾箱回库 = "尾箱回库"; } } Controllers/DebugController.cs
@@ -72,58 +72,6 @@ return DebugService.InsertLocCntrCg(); } public string AddCgCntrLocRel(CgInfo model) { var db = DbHelper.GetDbClient(); try { using (var tran = db.Ado.UseTran()) { var loc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.LocId); if (loc == null) { var newLoc = new TN_Location { S_CODE = model.LocId, N_CURRENT_NUM = 1 }; if (db.Insertable<TN_Location>(newLoc).ExecuteCommand() <= 0) { tran.RollbackTran(); return $"插入位置{model.LocId}失败"; } loc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.LocId); } if (loc.N_CURRENT_NUM == 0) { loc.N_CURRENT_NUM = 1; if (db.Updateable<TN_Location>(loc).UpdateColumns( it => new { it.N_CURRENT_NUM, it.T_MODIFY }).ExecuteCommand() <= 0) { tran.RollbackTran(); return $"修改位置{model.LocId}失败"; } } var locCntrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.LocId && a.S_CNTR_CODE == model.CntId); if (locCntrRel == null) { var locList = new List<TN_Loc_Container>(); locList.Add(new TN_Loc_Container { S_LOC_CODE = model.LocId, S_CNTR_CODE = model.CntId }); if (db.Insertable<TN_Loc_Container>(locList).ExecuteCommand() <= 0) { tran.RollbackTran(); return $"插入位置托盘关系{model.LocId}-{model.CntId}失败"; } } var cgDetail = db.Queryable<TN_CG_Detail>().First(a => a.S_CNTR_CODE == model.CntId && a.S_ITEM_CODE == model.ItemCode); if (cgDetail == null) { var locList = new List<TN_CG_Detail>(); locList.Add(new TN_CG_Detail { S_CNTR_CODE = model.CntId, S_ITEM_CODE = model.ItemCode }); if (db.Insertable<TN_CG_Detail>(locList).ExecuteCommand() <= 0) { tran.RollbackTran(); return $"插入托盘物料关系{model.CntId}-{model.ItemCode}失败"; } } tran.CommitTran(); } } catch (Exception ex) { return $"出错:{ex}"; } return "success"; } } public class CgInfo { Controllers/MoboxController.cs
@@ -25,47 +25,49 @@ /// <param name="model"></param> /// <returns></returns> [HttpPost] [Route("GoodpackOffline")] [Route("goodpack-offline")] public SimpleResult GoodpackOffline(GoodpackOfflineInfo model) { LogHelper.InfoApi("好运箱-满托下线入库(PDA)", model); return MoboxService.GoodpackOffline(model); } /// <summary> /// 空托/空箱绑定 /// </summary> /// <param name="model"></param> /// <returns></returns> public SimpleResult EmptyBind(EmptyBindInfo model) { LogHelper.InfoApi("空托/空箱绑定", model); ///// <summary> ///// 空托/空箱入库绑定(PDA) ///// </summary> ///// <param name="model"></param> ///// <returns></returns> //public SimpleResult EmptyBind(EmptyBindInfo model) { // LogHelper.InfoApi("空托/空箱绑定", model); if (model.CntrType == "托盘") { //LogHelper.Info($"触发API:空托绑定 " + JsonConvert.SerializeObject(model), "API"); return MoboxService.EmptyBindPallet(model); } else if (model.CntrType == "好运箱") { //LogHelper.Info($"触发API:空箱绑定 " + JsonConvert.SerializeObject(model), "API"); return MoboxService.EmptyBindGoodpack(model); } else { return BuildSimpleResult(-1, $"不合法的容器类型:'{model.CntrType}'"); } } // if (model.CntrType == "托盘") { // //LogHelper.Info($"触发API:空托绑定 " + JsonConvert.SerializeObject(model), "API"); // return MoboxService.EmptyBindPallet(model); // } // else if (model.CntrType == "好运箱") { // //LogHelper.Info($"触发API:空箱绑定 " + JsonConvert.SerializeObject(model), "API"); // return MoboxService.EmptyBindGoodpack(model); // } // else { // return BuildSimpleResult(-1, $"不合法的容器类型:'{model.CntrType}'"); // } //} /// <summary> /// 空托/空箱入库(PDA) /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] [Route("empty-inbound")] public SimpleResult EmptyInbound(EmptyInboundInfo model) { LogHelper.InfoApi("空托/空箱入库", model); var db = DbHelper.GetDbClient(); var locCntrRel = db.Queryable<TN_Loc_Container>() .Where(lc => lc.S_LOC_CODE == model.LocCode).First(); .Where(lc => lc.S_CNTR_CODE == model.CntrCode).First(); if (locCntrRel == null) { return BuildSimpleResult(-1, $"不存在已绑定容器的货位号:'{model.LocCode}'"); return BuildSimpleResult(-1, $"不存在已绑定容器的货位号:'{model.CnteType}'"); } if (locCntrRel.S_CNTR_TYPE == "托盘") { @@ -87,95 +89,146 @@ } } /// <summary> /// 空托/空箱上线(PDA) /// </summary> /// <returns> /// 人工使用PDA扫码,根据物料类型判断上线空托/空箱 /// </returns> public SimpleResult EmptyOnline(EmptyOnlineInfo model) { var db = DbHelper.GetDbClient(); var locCntrRel = db.Queryable<TN_Loc_Container>() .LeftJoin<TN_CG_Detail>((lc, cd) => lc.S_CNTR_CODE == cd.S_CNTR_CODE) .Where((lc, cd) => cd.S_ITEM_CODE == model.ItemCode) .First(); ///// <summary> ///// 空托/空箱上线(PDA) ///// </summary> ///// <returns> ///// 人工使用PDA扫码,根据物料类型判断上线空托/空箱 ///// </returns> //public SimpleResult EmptyOnline(EmptyOnlineInfo model) { // var db = DbHelper.GetDbClient(); // var locCntrRel = db.Queryable<TN_Loc_Container>() // .LeftJoin<TN_CG_Detail>((lc, cd) => lc.S_CNTR_CODE == cd.S_CNTR_CODE) // .Where((lc, cd) => cd.S_ITEM_CODE == model.ItemCode) // .First(); if (locCntrRel.S_CNTR_TYPE == "托盘") { // if (locCntrRel.S_CNTR_TYPE == "托盘") { return MoboxService.EmptyOnlinePallet(new EmptyOnlinePalletInfo { CntId = locCntrRel.S_CNTR_CODE, EndLoc = model.EndLoc }); } else if (locCntrRel.S_CNTR_TYPE == "好运箱") { // return MoboxService.EmptyOnlinePallet(new EmptyOnlinePalletInfo { // CntId = locCntrRel.S_CNTR_CODE, // EndLoc = model.EndLoc // }); // } // else if (locCntrRel.S_CNTR_TYPE == "好运箱") { return MoboxService.EmptyOnlineGoodpack(new EmptyOnlineGoodpackInfo { CntId = locCntrRel.S_CNTR_CODE, EndLoc = model.EndLoc }); } else { return BuildSimpleResult(-1, $"不合法的容器类型:'{locCntrRel.S_CNTR_CODE}'"); } } // return MoboxService.EmptyOnlineGoodpack(new EmptyOnlineGoodpackInfo { // CntId = locCntrRel.S_CNTR_CODE, // EndLoc = model.EndLoc // }); // } // else { // return BuildSimpleResult(-1, $"不合法的容器类型:'{locCntrRel.S_CNTR_CODE}'"); // } //} /// <summary> /// 创建抽检单 /// 托盘-空托上线(PDA) /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] [Route("empty-online-pallet")] public SimpleResult EmptyOnlinePallet(EmptyOnlinePalletInfo model) { return MoboxService.EmptyOnlinePallet(model); } /// <summary> /// 好运箱-空箱上线(PDA) /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] [Route("empty-online-goodpack")] public SimpleResult EmptyOnlineGoodpack(EmptyOnlineGoodpackInfo model) { return MoboxService.EmptyOnlineGoodpack(model); } ///// <summary> ///// 合格回库/不合格移库 ///// </summary> ///// <param name="model"></param> ///// <returns></returns> //[HttpPost] //[Route("CheckShift")] //public SimpleResult CheckShift(CheckShiftInfo model) { // LogHelper.InfoApi("合格回库/不合格移库", model); // if (model.Qualified) { // return MoboxService.QualifiedBack(model); // } // else { // return MoboxService.UnqualifiedShift(model); // } //} /// <summary> /// 合格回库(PDA) /// </summary> /// <returns></returns> [HttpPost] [Route("qualified-back")] public SimpleResult QualifiedBack(QualifiedBackInfo model) { return MoboxService.QualifiedBack(model); } /// <summary> /// 不合格移库(PDA) /// </summary> /// <returns></returns> [HttpPost] [Route("unqualified-shift")] public SimpleResult UnqualifiedShift(UnqualifiedShiftInfo model) { return MoboxService.UnqualifiedShift(model); } /// <summary> /// 余料尾箱回库(PDA) /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] [Route("rest-back")] public SimpleResult RestBack(RestBackInfo model) { return MoboxService.RestBack(model); } #endregion #region Mobox 接口 /// <summary> /// 成品胶出库(PDA) /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] [Route("finished-outbound")] public SimpleResult FinishedOutbound(FinishedOutboundInfo model) { LogHelper.InfoApi("成品胶出库(PDA)", model); if (model.ForcedOut) { return MoboxService.FinishedOutboundForce(model); } return MoboxService.FinishedOutbound(model); } /// <summary> /// 抽检-创建抽检单(WMS) /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] [Route("create-check-order")] public SimpleResult CreateCheckOrder(CreateCheckOrderInfo model) { return MoboxService.CreateCheckOrder(model); } /// <summary> /// 合格回库/不合格移库 /// 移库-创建移库任务(WMS) /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] [Route("CheckShift")] public SimpleResult CheckShift(CheckShiftInfo model) { LogHelper.InfoApi("合格回库/不合格移库", model); if (model.Qualified) { return MoboxService.QualifiedBack(model); } else { return MoboxService.UnqualifiedShift(model); } } ///// <summary> ///// 合格回库 ///// </summary> ///// <returns></returns> //public SimpleResult QualifiedBack(QualifiedBackInfo model) { // return new SimpleResult(); //} ///// <summary> ///// 不合格移库 ///// </summary> ///// <returns></returns> //public SimpleResult UnqualifiedShift() { // return new SimpleResult(); //} #endregion #region Mobox 接口 /// <summary> /// 成品胶出库(WMS) /// </summary> /// <param name="model"></param> /// <returns></returns> public SimpleResult FinishedOutbound(FinishedOutboundInfo model) { LogHelper.InfoApi("成品胶出库(WMS)", model); if (model.ForcedOut) { return MoboxService.FinishedOutboundForce(model); } return MoboxService.FinishedOutbound(model); [Route("shift-storage")] public SimpleResult CreateShiftOrder(CreateShiftOrderInfo model) { return MoboxService.CreateShiftOrder(model); } #endregion } Dtos/Request/AgvRequest.cs
@@ -34,7 +34,7 @@ /// 请求码 /// </summary> public string apply_code { get; set; } public string TaskNo { set; get; } public string task_no { set; get; } } } } Dtos/Request/MoboxRequest.cs
@@ -1,42 +1,79 @@ using Newtonsoft.Json; using System.ComponentModel.DataAnnotations; using Newtonsoft.Json; namespace HH.WCS.Mobox3.DSZSH.Dtos.Request { public class MoboxRequest { #region PDA 数据 /// <summary> /// 成品胶好运箱下线信息 /// 好运箱-满托下线入库(PDA)数据类 /// </summary> public class GoodpackOfflineInfo : StartCntInfo { public string CgId { get; set; } public class GoodpackOfflineInfo { /// <summary> /// 物料编码 /// </summary> [JsonProperty("s_item_code")] public string ItemCode { get; set; } ///// <summary> ///// 物料名称 ///// </summary> // //[JsonProperty("item_name")] //public string ItemName { get; set; } /// <summary> /// 批次号 /// </summary> [JsonProperty("s_batch_no")] public string BatchNo { get; set; } /// <summary> /// 物料规格 /// </summary> [JsonProperty("s_spec")] public string Spec { get; set; } /// <summary> /// 数量 /// </summary> [JsonProperty("n_num")] public int Qty { get; set; } /// <summary> /// 货位信息 /// </summary> [JsonProperty("s_start_loc")] public string StartLoc { get; set; } } /// <summary> /// API:空托/空箱绑定数据类 /// 空托/空箱入库绑定(PDA)数据类 /// </summary> public class EmptyBindInfo { /// <summary> /// 容器编码 /// </summary> [JsonProperty("s_cntr_code")] public string CntrCode { get; set; } /// <summary> /// 容器类型 /// </summary> [JsonProperty("s_cntr_type")] public string CntrType { get; set; } /// <summary> /// 托盘数量(仅当容器类型为托盘时使用) /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public int PalletCount { get; set; } ///// <summary> ///// 托盘数量(仅当容器类型为托盘时使用) ///// </summary> //[JsonProperty("pallet_count", NullValueHandling = NullValueHandling.Ignore)] //public int PalletCount { get; set; } /// <summary> /// 货位编码 /// </summary> [JsonProperty("s_loc_code")] public string LocCode { get; set; } } /// <summary> /// 空托绑定 /// </summary> public class EmptyBindPalletInfo { /// <summary> /// 容器编码 @@ -53,7 +90,9 @@ /// </summary> public string LocCode { get; set; } } /// <summary> /// 空箱绑定 /// </summary> public class EmptyBindGoodpackInfo { /// <summary> /// 容器编码 @@ -65,48 +104,141 @@ /// </summary> public string LocCode { get; set; } } /// <summary> /// 空托/空箱入库(PDA)数据类 /// </summary> public class EmptyInboundInfo { /// <summary> /// 货位编码 /// 容器编码 /// </summary> public string LocCode { get; set; } [JsonProperty("cntr_code")] public string CntrCode { get; set; } /// <summary> /// 容器类型 /// </summary> [JsonProperty("cntr_type")] public string CnteType { get; set; } /// <summary> /// 终点库区编码 /// </summary> [JsonProperty("end_area")] public string EndArea { get; set; } } public class EmptyInboundDetailInfo : StartCntInfo { } public class EmptyOnlineInfo { public string ItemCode { get; set; } public string ItemName { get; set; } public string PatchNo { get; set; } public string EndLoc { get; set; } } //public class EmptyOnlineInfo { // public string ItemCode { get; set; } // public string ItemName { get; set; } // public string PatchNo { get; set; } // public string EndLoc { get; set; } //} public class EmptyOnlinePalletInfo { public string CntId { get; set; } public string EndLoc { get; set; } } public class EmptyOnlineGoodpackInfo : StartCntEndInfo { } public class CreateCheckOrderInfo { public string No { get; set; } public string CgId { get; set; } public string ItemName { get; set; } /// <summary> /// 物料编码 /// </summary> [JsonProperty("item_code")] public string ItemCode { get; set; } ///// <summary> ///// 物料名称 ///// </summary> // //[JsonProperty("item_name")] //public string ItemName { get; set; } /// <summary> /// 批次号 /// </summary> [JsonProperty("batch_no")] public string BatchNo { get; set; } /// <summary> /// 抽检数量 /// 物料规格 /// </summary> public int N_QTY { get; set; } [JsonProperty("spe")] public string Spe { get; set; } /// <summary> /// 容器编码 /// </summary> [JsonProperty("cnt_id")] public string CntId { get; set; } // 容器类型 = 托盘 } public class EmptyOnlineGoodpackInfo { // 容器类型 = 好运箱 /// <summary> /// 容器编码 /// </summary> [JsonProperty("cnt_id")] public string CntId { get; set; } } /// <summary> /// 抽检-创建抽检单(WMS)数据类 /// </summary> public class CreateCheckOrderInfo { /// <summary> /// 物料编码 /// </summary> [JsonProperty("item_code")] public string ItemCode { get; set; } ///// <summary> ///// 物料名称 ///// </summary> // //[JsonProperty("item_name")] //public string ItemName { get; set; } /// <summary> /// 物料规格 /// </summary> [JsonProperty("spe")] public string Spe { get; set; } /// <summary> /// 批次号 /// </summary> [JsonProperty("batch_no")] public string BatchNo { get; set; } /// <summary> /// 需出库数量 /// </summary> [JsonProperty("qty")] public int Qty { get; set; } /// <summary> /// 容器类型 /// </summary> [JsonProperty("cntr_type")] public string CntrType { get; set; } /// <summary> /// 出库终点货区 /// </summary> [JsonProperty("end_area")] public string EndArea { get; set; } } public class QualifiedBackInfo { /// <summary> /// 物料编码 /// </summary> [JsonProperty("item_code")] public string ItemCode { get; set; } /// <summary> /// 容器编码 /// </summary> [JsonProperty("cntr_code")] public string CntrCode { get; set; } } public class UnqualifiedShiftInfo : QualifiedBackInfo { /// <summary> /// 不合格移库终点库区 /// </summary> [JsonProperty("end_area")] public string EndArea { get; set; } } @@ -118,49 +250,102 @@ #region WMS 数据 /// <summary> /// 成品胶托盘出库信息 /// 成品胶出库(PDA) /// </summary> public class FinishedOutboundInfo { //public string No { get; set; } /// <summary> /// 物料编码 /// </summary> [JsonProperty("item_code")] public string ItemCode { get; set; } public string ItemName { get; set; } ///// <summary> ///// 物料名称 ///// </summary> // //[JsonProperty("item_name")] //public string ItemName { get; set; } /// <summary> /// 物料规格 /// </summary> [JsonProperty("spe")] public string Spe { get; set; } /// <summary> /// 批次号 /// </summary> [JsonProperty("batch_no")] public string BatchNo { get; set; } /// <summary> /// 需出库数量 /// </summary> [JsonProperty("qty")] public int Qty { get; set; } /// <summary> /// 容器类型 /// </summary> [JsonProperty("cntr_type")] public string CntrType { get; set; } public float Qty { get; set; } /// <summary> /// 出库终点货区 /// </summary> [JsonProperty("end_area")] public string EndArea { get; set; } /// <summary> /// 是否强制出库 /// </summary> [JsonProperty("force_out")] public bool ForcedOut { get; set; } } /// <summary> /// 移库-创建移库任务数据类 /// </summary> public class CreateShiftOrderInfo { /// <summary> /// 物料编码 /// </summary> [JsonProperty("item_code")] public string ItemCode { get; set; } ///// <summary> ///// 物料名称 ///// </summary> // //[JsonProperty("item_name")] //public string ItemName { get; set; } /// <summary> /// 批次号 /// </summary> [JsonProperty("batch_no")] public string BatchNo { get; set; } /// <summary> /// 移库终点货区 /// </summary> [JsonProperty("end_area")] public string EndArea { get; set; } } /// <summary> /// 余料尾箱回库(PDA)数据类 /// </summary> public class RestBackInfo { /// <summary> /// 起点货位 /// </summary> [JsonProperty("start_loc")] public string StartLoc { get; set; } } #endregion //------------------------------------------------------------------------------ #region 模板数据 /// <summary> /// 模板抽象数据类:起点货位、容器号、终点货位 /// </summary> public abstract class StartCntEndInfo { /// <summary> /// 起点货位 /// </summary> public string StartLoc { get; set; } /// <summary> /// 容器号 /// </summary> public string CntId { get; set; } /// <summary> /// 终点货位 /// </summary> public string EndLoc { get; set; } } /// <summary> /// 模板抽象数据类:起点货位、容器号 /// </summary> Dtos/Response/MoboxResponse.cs
@@ -9,9 +9,10 @@ namespace HH.WCS.Mobox3.DSZSH.Dtos.Response { public class MoboxResponse { /// <summary> /// Mobox 接口返回 /// Mobox 接口返回数据类 /// </summary> public class SimpleResult { [JsonProperty("resultCode")] public int Code { get; set; } HH.WCS.Mobox3.DSZSH.csproj
@@ -53,6 +53,10 @@ <PropertyGroup> <StartupObject>HH.WCS.Mobox3.DSZSH.Program</StartupObject> </PropertyGroup> <PropertyGroup> <GenerateDocumentationFile>true</GenerateDocumentationFile> <NoWarn>$(NoWarn);1591</NoWarn> </PropertyGroup> <ItemGroup> <Reference Include="BouncyCastle.Crypto, Version=1.9.0.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL"> <HintPath>packages\Portable.BouncyCastle.1.9.0\lib\net40\BouncyCastle.Crypto.dll</HintPath> @@ -129,11 +133,15 @@ <Reference Include="Swashbuckle.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cd1bb07a5ac7c7bc, processorArchitecture=MSIL"> <HintPath>..\packages\Swashbuckle.Core.5.6.0\lib\net40\Swashbuckle.Core.dll</HintPath> </Reference> <Reference Include="Swashbuckle.Examples, Version=4.1.0.0, Culture=neutral, PublicKeyToken=aa1e9c5053bfbe95, processorArchitecture=MSIL"> <HintPath>packages\Swashbuckle.Examples.4.1.0\lib\net40\Swashbuckle.Examples.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath> </Reference> <Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.Configuration" /> <Reference Include="System.Configuration.Install" /> <Reference Include="System.Core" /> @@ -216,7 +224,8 @@ </Reference> </ItemGroup> <ItemGroup> <Compile Include="AppStart\Config.cs" /> <Compile Include="App_Start\Config.cs" /> <Compile Include="App_Start\SwaggerConfig.cs" /> <Compile Include="Consts\AgvStateCode.cs" /> <Compile Include="Consts\AgvStateName.cs" /> <Compile Include="Consts\AreaName.cs" /> @@ -228,7 +237,7 @@ <Compile Include="Controllers\ErpController.cs" /> <Compile Include="Controllers\MoboxController.cs" /> <Compile Include="Controllers\AgvController.cs" /> <Compile Include="AppStart\SwaggerControllerDescProvider.cs" /> <Compile Include="App_Start\SwaggerControllerDescProvider.cs" /> <Compile Include="Models\DebugModel.cs" /> <Compile Include="Dtos\Request\DebugRequest.cs" /> <Compile Include="Dtos\Response\DebugResponse.cs" /> @@ -244,8 +253,11 @@ <Compile Include="Models\TN_Order_Task.cs" /> <Compile Include="Models\TN_Outbound_Order.cs" /> <Compile Include="Models\TN_Outbound_Detail.cs" /> <Compile Include="Models\TN_Shift_Detail.cs" /> <Compile Include="Models\TN_Shift_Order.cs" /> <Compile Include="ServiceCore\CheckCore.cs" /> <Compile Include="ServiceCore\OutboundCore.cs" /> <Compile Include="ServiceCore\ShiftCore.cs" /> <Compile Include="Services\DebugService.cs" /> <Compile Include="Devices\ProductionLineDevice.cs" /> <Compile Include="Devices\ModbusHelper.cs" /> @@ -285,8 +297,8 @@ <Compile Include="Helpers\SysHelper.cs" /> <Compile Include="Program.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="AppStart\Settings.cs" /> <Compile Include="AppStart\Startup.cs" /> <Compile Include="App_Start\Settings.cs" /> <Compile Include="App_Start\Startup.cs" /> <Compile Include="Dispatch\NDCHelper.cs" /> <Compile Include="Helpers\HttpHelper.cs" /> </ItemGroup> Models/TN_CG_Detail.cs
@@ -17,6 +17,11 @@ public string S_ITEM_CODE { get; set; } /// <summary> /// 物料规格 /// </summary> public string S_SPE { get; set; } /// <summary> /// 容器编码 /// </summary> public string S_CNTR_CODE { get; set; } @@ -39,6 +44,6 @@ /// <summary> /// 货品数量 /// </summary> public float F_QTY { get; set; } public int N_QTY { get; set; } } } Models/TN_Check_Detail.cs
@@ -14,8 +14,9 @@ public class TN_Check_Detail : BaseModel { public string S_NO { get; set; } public string S_CG_ID { get; set; } public string S_ITEM_NAME { get; set; } public string S_ITEM_CODE { get; set; } //public string S_ITEM_NAME { get; set; } public string S_BATCH_NO { get; set; } public string S_END_AREA { get; set; } /// <summary> Models/TN_Check_Order.cs
@@ -13,7 +13,7 @@ [SugarTable("TN_Check_Order")] public class TN_Check_Order : BaseModel { public string S_NO { get; set; } public string S_CG_ID { get; set; } public string S_ITEM_CODE { get; set; } public string S_ITEM_NAME { get; set; } public string S_BATCH_NO { get; set; } public int N_COUNT { get; set; } Models/TN_Shift_Detail.cs
New file @@ -0,0 +1,25 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HH.WCS.Mobox3.DSZSH.Models { internal class TN_Shift_Detail : BaseModel { public string S_NO { get; set; } public string S_ITEM_CODE { get; set; } public string S_ITEM_NAME { get; set; } public string S_LOC_CODE { get; set; } public string S_CNTR_CODE { get; set; } public string S_BATCH_NO { get; set; } public string S_END_AREA { get; set; } /// <summary> /// 业务状态:0等待执行 1已执行待生成任务 2任务执行中 3任务完成 /// </summary> public int N_B_STATE { get; set; } = 1; // 创建即执行 } } Models/TN_Shift_Order.cs
New file @@ -0,0 +1,23 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HH.WCS.Mobox3.DSZSH.Models { /// <summary> /// 移库单 /// </summary> public class TN_Shift_Order : BaseModel { public string S_NO { get; set; } public string S_ITEM_CODE { get; set; } public string S_ITEM_NAME { get; set; } public string S_BATCH_NO { get; set; } public int N_COUNT { get; set; } public string S_END_AREA { get; set; } /// <summary> /// 业务状态:0等待执行 1已执行待生成任务 2任务执行中 3任务完成 /// </summary> public int N_B_STATE { get; set; } = 0; // 创建后需要确认执行 } } ServiceCore/CheckCore.cs
@@ -30,7 +30,7 @@ foreach (var detail in detailList) { var startLocCntrRel = db.Queryable<TN_Location, TN_Loc_Container, TN_CG_Detail> ((l, c, d) => l.S_CODE == c.S_LOC_CODE && c.S_CNTR_CODE == d.S_CNTR_CODE) .Where((l, c, d) => d.S_ITEM_CODE == detail.S_CG_ID && d.S_BATCH_NO == detail.S_BATCH_NO) .Where((l, c, d) => d.S_ITEM_CODE == detail.S_ITEM_CODE && d.S_BATCH_NO == detail.S_BATCH_NO) .Select((l, c) => c) // 选择 LocCntrRel .First(); // 随机抽检,不排序 ServiceCore/ShiftCore.cs
New file @@ -0,0 +1,117 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using HH.WCS.Mobox3.DSZSH.Consts; using HH.WCS.Mobox3.DSZSH.Helpers; using HH.WCS.Mobox3.DSZSH.Models; namespace HH.WCS.Mobox3.DSZSH.ServiceCore { /// <summary> /// 移库业务核心 /// </summary> internal class ShiftCore { public static void CheckOrderState() { var db = DbHelper.GetDbClient(); // 目前按出库的逻辑:逐个移库 try { var order = db.Queryable<TN_Shift_Order>() .Where(c => c.N_B_STATE == SpotStateCode.已执行待生成任务) .OrderBy(c => c.T_CREATE, SqlSugar.OrderByType.Asc).First(); if (order == null) { LogHelper.Info("轮询:暂无待执行的移库单"); return; } if (db.Queryable<TN_Shift_Detail>() .First(d => d.S_NO == order.S_NO && d.N_B_STATE == SpotStateCode.任务执行中) != null) { LogHelper.Debug("轮询:上一个移库任务仍在进行中"); return; } var detail = db.Queryable<TN_Shift_Detail>() .Where(d => d.S_NO == order.S_NO && d.N_B_STATE == SpotStateCode.已执行待生成任务) .OrderBy(d => d.T_CREATE, SqlSugar.OrderByType.Asc).First(); if (detail == null) { //order.N_B_STATE = SpotStateCode.任务执行中; LogHelper.Info("轮询移库:暂无待执行的任务"); return; } var startLocCntrRel = db.Queryable<TN_Loc_Container>() .Where(c => c.S_CNTR_CODE == detail.S_CNTR_CODE) .First(); if (startLocCntrRel == null) { LogHelper.Info("轮询:移库:没有找到合适的起点货位"); return; } var endLoc = db.Queryable<TN_Location>() .Where(l => l.S_AREA_CODE == detail.S_END_AREA) .Where(ExprHelper.LocIsFree) .Where(ExprHelper.LocIsEmpty).First(); if (endLoc == null) { LogHelper.Info("轮询:出库:没有找到合适的终点货位"); return; } using (var tran = db.Ado.UseTran()) { detail.N_B_STATE = SpotStateCode.任务执行中; if (db.Updateable<TN_Shift_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) { tran.RollbackTran(); LogHelper.Info($"轮询:出库:更新失败:修改明细表状态为完成"); } if (TaskHelper.LogCreateTask(startLocCntrRel.S_LOC_CODE, startLocCntrRel.S_CNTR_CODE, endLoc.S_CODE, TaskName.成品胶出库)) { tran.CommitTran(); } else { tran.RollbackTran(); } } } catch (Exception ex) { LogHelper.InfoEx(ex); } } public static void UpdateTaskState(int spotStateCode) { var db = DbHelper.GetDbClient(); var detail = db.Queryable<TN_Shift_Detail>() .First(d => d.N_B_STATE == SpotStateCode.任务执行中); if (detail == null) { LogHelper.Info("当前没有执行中的移库单明细项目"); return; } using (var tran = db.Ado.UseTran()) { detail.N_B_STATE = spotStateCode; db.Updateable<TN_Shift_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand(); if (db.Queryable<TN_Shift_Detail>().Count(d => d.S_NO == detail.S_NO && d.N_B_STATE == 2) == db.Queryable<TN_Shift_Detail>().Count(d => d.S_NO == detail.S_NO)) { if (db.Updateable<TN_Shift_Order>().SetColumns(it => it.N_B_STATE == SpotStateCode.任务执行完成) .Where(it => it.S_NO == detail.S_NO) .ExecuteCommand() <= 0) { tran.RollbackTran(); LogHelper.Info("修改Order状态错误"); } } tran.CommitTran(); } } } } Services/AgvService.cs
@@ -19,8 +19,8 @@ try { switch (model.state) { case 1023: break; case 1025: break; case 1012: break; @@ -117,9 +117,7 @@ return true; } public static ReturnResult SafetyInteraction(SafetyInteractionInfo model) { var gzResult = new ReturnResult(); var db = DbHelper.GetDbClient(); @@ -134,9 +132,9 @@ LogHelper.Info("加载设备信息失败"); } var tn_task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.TaskNo); var tn_task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.task_no); if (tn_task == null) { LogHelper.Info($"任务号 '{model.TaskNo}' 不存在"); LogHelper.Info($"任务号 '{model.task_no}' 不存在"); } // 待修改:补充不同分支AGV判断 Services/MoboxService.cs
@@ -18,45 +18,6 @@ namespace HH.WCS.Mobox3.DSZSH.Services { public class MoboxService { #region 模板功能 public static SimpleResult BaseBound(StartCntEndInfo model) { var taskName = ""; // 用于生成任务类型、打印日志信息 var db = DbHelper.GetDbClient(); try { var startLoc = db.Queryable<TN_Location>() .Where(ExprHelper.LocCode(model.StartLoc)) .Where(ExprHelper.LocIsFree) .Where(ExprHelper.LocIsEmpty.Negate()).First(); if (startLoc == null) { return BuildSimpleResult(2, $"起点位置 '{model.StartLoc}' 不存在或不具备取货要求"); } var locCntrRel = db.Queryable<TN_Loc_Container>() .Where(ExprHelper.LocCntrIsBind(startLoc.S_CODE, model.CntId)).First(); if (locCntrRel == null) { return BuildSimpleResult(3, $"起点位置 '{startLoc.S_CODE}' 没有绑定容器 '{model.CntId}'"); } var endLoc = db.Queryable<TN_Location>() .Where(ExprHelper.LocCode(model.EndLoc)) .Where(ExprHelper.LocIsFree) .Where(ExprHelper.LocIsEmpty).First(); if (endLoc == null) { return BuildSimpleResult(4, $"终点位置 '{model.EndLoc}' 不存在或不具备放货要求"); } return TaskHelper.SimpleCreateTask(startLoc.S_CODE, locCntrRel.S_CNTR_CODE, endLoc.S_CODE, taskName); } catch (Exception ex) { return BuildSimpleEx(ex); } } #endregion #region PDA 功能 /// <summary> /// 好运箱-满托下线入库(PDA) @@ -82,10 +43,9 @@ // 查看容器与起点货位是否绑定 var locCntrRel = db.Queryable<TN_Loc_Container>().First( a => a.S_LOC_CODE == model.StartLoc && a.S_CNTR_CODE == model.CntId); a => a.S_LOC_CODE == startLoc.S_CODE); if (locCntrRel == null) { return BuildSimpleResult(3, $"起点位置 '{model.StartLoc}' 没有绑定容器 '{model.CntId}' ,无可出库的物料"); return BuildSimpleResult(3, $"起点位置 '{model.StartLoc}' 无可出库的物料"); } // TODO 满箱入库算法待优化 @@ -133,7 +93,7 @@ return BuildSimpleResult(3, $"当前容器 '{model.CntrCode}' 已经与 '{locCntrRel.S_LOC_CODE}' 绑定"); } loc.N_CURRENT_NUM = model.PalletCount; //loc.N_CURRENT_NUM = model.PalletCount; locCntrRel = new TN_Loc_Container { S_LOC_CODE = model.LocCode, @@ -325,13 +285,13 @@ } var endLoc = db.Queryable<TN_Location>() .Where(ExprHelper.LocCode(model.EndLoc)) .Where(ExprHelper.LocBelongsToArea(AreaName.包装区)) .Where(l => taskInfo.EndAreas.Contains(l.S_AREA_CODE)) .Where(ExprHelper.LocIsFree) .Where(ExprHelper.LocIsEmpty).First(); if (endLoc == null) { return BuildSimpleResult(4, $"终点位置 '{model.EndLoc}' 不存在或不具备放货要求"); return BuildSimpleResult(4, $"终点位置 不存在或不具备放货要求"); } return TaskHelper.SimpleCreateTask(startLoc.S_CODE, locCntrRel.S_CNTR_CODE, endLoc.S_CODE, taskName); @@ -371,13 +331,13 @@ } var endLoc = db.Queryable<TN_Location>() .Where(ExprHelper.LocCode(model.EndLoc)) .Where(ExprHelper.LocBelongsToArea(AreaName.包装区)) .Where(l => taskInfo.EndAreas.Contains(l.S_AREA_CODE)) .Where(ExprHelper.LocIsFree) .Where(ExprHelper.LocIsEmpty).First(); if (endLoc == null) { return BuildSimpleResult(4, $"终点位置 '{model.EndLoc}' 不存在或不具备放货要求"); return BuildSimpleResult(4, $"终点位置 不存在或不具备放货要求"); } return TaskHelper.SimpleCreateTask(startLoc.S_CODE, locCntrRel.S_CNTR_CODE, endLoc.S_CODE, taskName); @@ -399,11 +359,11 @@ using (var tran = db.Ado.UseTran()) { var order = new TN_Check_Order { S_NO = model.No, S_CG_ID = model.CgId, S_ITEM_NAME = model.ItemName, S_NO = GenerateOrderNo("抽检单号", "CN"), S_ITEM_CODE = model.ItemCode, //S_ITEM_NAME = model.ItemName, S_BATCH_NO = model.BatchNo, N_COUNT = model.N_QTY, N_COUNT = model.Qty, S_END_AREA = model.EndArea, }; @@ -412,10 +372,10 @@ return BuildSimpleResult(2, "生成 抽检单 失败:" + JsonConvert.SerializeObject(order)); } for (int i = 0; i < model.N_QTY; i++) { for (int i = 0; i < model.Qty; i++) { var detail = new TN_Check_Detail { S_NO = model.No, S_CG_ID = model.CgId, S_NO = order.S_NO, S_ITEM_CODE = model.ItemCode, S_BATCH_NO = model.BatchNo, S_END_AREA = model.EndArea }; @@ -428,7 +388,7 @@ tran.CommitTran(); } return BuildSimpleResult(0, $"创建 抽检单 成功:单号 {model.No}"); return BuildSimpleResult(0, $"创建 抽检单 成功"); } catch (Exception ex) { return BuildSimpleEx(ex); @@ -437,6 +397,7 @@ public static SimpleResult QualifiedBack(QualifiedBackInfo model) { var db = DbHelper.GetDbClient(); try { var cgDetail = db.Queryable<TN_CG_Detail>() @@ -549,6 +510,34 @@ } } public static SimpleResult RestBack(RestBackInfo model) { var db = DbHelper.GetDbClient(); try { var locCntrRel = db.Queryable<TN_Loc_Container>() .Where(c => c.S_LOC_CODE == model.StartLoc) .First(); if (locCntrRel == null) { return BuildSimpleResult(2, $"起点货位 {model.StartLoc}"); } var endLoc = db.Queryable<TN_Location, TN_Loc_Container>((l, c) => l.S_CODE == c.S_LOC_CODE) .Where((l, c) => c.S_CNTR_TYPE == locCntrRel.S_CNTR_TYPE) .First(); if (endLoc == null) { return BuildSimpleResult(3, $"不存在合适的终点货位可以回库"); } return TaskHelper.SimpleCreateTask(locCntrRel.S_LOC_CODE, locCntrRel.S_CNTR_CODE, endLoc.S_CODE, TaskName.尾箱回库); } catch (Exception ex) { return BuildSimpleEx(ex); } } #endregion #region Mobox 功能 @@ -598,7 +587,7 @@ S_ITEM_CODE = model.ItemCode, S_BATCH_NO = model.BatchNo, F_QTY = model.Qty, F_OUT_QTY = cgDetailList.Sum(a => a.F_QTY), F_OUT_QTY = cgDetailList.Sum(a => a.N_QTY), S_END_AREA = model.EndArea }; @@ -659,7 +648,7 @@ S_ITEM_CODE = model.ItemCode, S_BATCH_NO = model.BatchNo, F_QTY = model.Qty, F_OUT_QTY = cgDetailList.Sum(a => a.F_QTY), F_OUT_QTY = cgDetailList.Sum(a => a.N_QTY), S_END_AREA = model.EndArea }; @@ -685,8 +674,8 @@ try { var targetCg = db.Queryable<TN_CG_Detail>().Where(a => a.S_ITEM_CODE == model.ItemCode && a.F_QTY > targetNum). OrderBy(a => a.F_QTY, OrderByType.Asc).First(); && a.N_QTY > targetNum). OrderBy(a => a.N_QTY, OrderByType.Asc).First(); if (targetCg != null) //刚好有一行满足条件 { result.Add(targetCg); @@ -695,12 +684,12 @@ // NOTE 根据总量选detail时,是否需要考虑货位的高低? var sortedMaterials = db.Queryable<TN_CG_Detail, TN_Loc_Container>((d, c) => d.S_CNTR_CODE == c.S_CNTR_CODE) .Where(d => d.S_ITEM_CODE == model.ItemCode && d.S_BATCH_NO == model.BatchNo && d.F_QTY > 0) .Where(d => d.S_ITEM_CODE == model.ItemCode && d.S_BATCH_NO == model.BatchNo && d.N_QTY > 0) .Where((d, c) => c.S_CNTR_TYPE == model.CntrType) .Where(d => (model.ForcedOut && d.N_ITEM_STATE == 0 && d.S_ITEM_STATE == "合格") || (!model.ForcedOut && (d.N_ITEM_STATE == 0 && d.S_ITEM_STATE == "合格" || d.N_ITEM_STATE == 1 && d.S_ITEM_STATE == "待检"))) .OrderBy(d => d.F_QTY, OrderByType.Desc) .OrderBy(d => d.N_QTY, OrderByType.Desc) .OrderBy(d => d.N_ITEM_STATE, OrderByType.Asc).ToList(); if (sortedMaterials.Count == 0)//没有满足条件的 @@ -710,13 +699,13 @@ float countNum = 0; foreach (var mat in sortedMaterials) { countNum += mat.F_QTY; countNum += mat.N_QTY; result.Add(mat); if (countNum >= targetNum) { break; } } if (result.Sum(a => a.F_QTY) >= targetNum) { if (result.Sum(a => a.N_QTY) >= targetNum) { return result; } else { @@ -729,6 +718,64 @@ } } /// <summary> /// 移库-创建移库任务(WMS) /// </summary> /// <param name="model"></param> /// <returns></returns> public static SimpleResult CreateShiftOrder(CreateShiftOrderInfo model) { var db = DbHelper.GetDbClient(); try { var locCntrRelList = db.Queryable<TN_Loc_Container, TN_CG_Detail>((c, d) => c.S_CNTR_CODE == d.S_CNTR_CODE) .Where((c, d) => d.S_ITEM_CODE == model.ItemCode && d.S_BATCH_NO == model.ItemCode) .ToList(); if (locCntrRelList.Count == 0) { return BuildSimpleResult(2, "没有找到待移库的物料"); } // 绑定操作:插入出库单、所有的出库单明细 using (var tran = db.Ado.UseTran()) { var order = new TN_Shift_Order { S_NO = GenerateOrderNo("移库单号", "SN"), S_ITEM_CODE = model.ItemCode, //S_ITEM_NAME = model.ItemName, S_BATCH_NO = model.BatchNo, N_COUNT = locCntrRelList.Count, S_END_AREA = model.EndArea, }; if (db.Insertable<TN_Shift_Order>(order).ExecuteCommand() <= 0) { tran.RollbackTran(); return BuildSimpleResult(2, "生成 移库单 失败:" + JsonConvert.SerializeObject(order)); } foreach (var locCntrRel in locCntrRelList) { var detail = new TN_Shift_Detail { S_NO = order.S_NO, S_ITEM_CODE = model.ItemCode, S_LOC_CODE = locCntrRel.S_LOC_CODE, S_CNTR_CODE = locCntrRel.S_CNTR_CODE, S_BATCH_NO = model.BatchNo, S_END_AREA = model.EndArea }; if (db.Insertable<TN_Shift_Detail>(detail).ExecuteCommand() <= 0) { tran.RollbackTran(); return BuildSimpleResult(3, "生成 移库单明细 失败:" + JsonConvert.SerializeObject(detail)); } } tran.CommitTran(); } return BuildSimpleResult(0, $"创建 移库单 成功"); } catch (Exception ex) { return BuildSimpleEx(ex); } } private static string GenerateOrderNo(string snType, string prefix) { var id = SysHelper.GetSerialNumber(snType, prefix); var date = DateTime.Now.ToString("yyMMdd"); config/config.json
@@ -1,5 +1,5 @@ { "WebApiUrl": "http://127.0.0.1:8901/", "WebApiUrl": "http://192.168.1.141:8901/", "NdcApiUrl": "http://127.0.0.1:5201/api/order/", "SqlServer": "Data Source=(local);Initial Catalog=DSZSHTest;User ID=sa;Password=123456;", "TcpServerIp": "127.0.0.1", packages.config
@@ -33,6 +33,7 @@ <package id="SqlSugar" version="5.1.4.169" targetFramework="net462" /> <package id="Swashbuckle" version="5.6.0" targetFramework="net461" /> <package id="Swashbuckle.Core" version="5.6.0" targetFramework="net461" /> <package id="Swashbuckle.Examples" version="4.1.0" targetFramework="net462" /> <package id="System.Buffers" version="4.5.1" targetFramework="net461" /> <package id="System.Diagnostics.DiagnosticSource" version="6.0.1" targetFramework="net462" /> <package id="System.Formats.Asn1" version="8.0.1" targetFramework="net462" /> swagger.js
@@ -40,6 +40,27 @@ } }); }, setModelDescriptions: function() { $.ajax({ type: "get", url: $("#input_baseUrl").val(), dataType: "json", success: function(data) { var modelDesc = data.ModelDesc; // 在模型展示区域添加描述 $(".model-box").each(function() { var modelName = $(this).find(".model-title").text(); if (modelDesc[modelName]) { $(this).find(".model-description").remove(); $(this).append( `<div class="model-description">${modelDesc[modelName]}</div>` ); } }); } }); }, _tryTranslate: function (word) { return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;