From 8e279bdd8a081a1d1cbac5fff08d3ef6b32d607d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=AD=A3=E6=98=93?= <9634538+git_rabbit@user.noreply.gitee.com> Date: Thu, 28 Mar 2024 11:17:18 +0800 Subject: [PATCH] =?UTF-8?q?WMS=E4=BB=93=E5=BA=93-=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E7=AE=B1=E6=A0=87=E7=AD=BE=E5=8A=9F=E8=83=BD=E6=8F=90=E5=8F=96?= =?UTF-8?q?=E5=88=B0MaterialUtils=E5=86=85=EF=BC=8C=E5=85=A5=E5=BA=93?= =?UTF-8?q?=EF=BC=8C=E5=87=BA=E5=BA=93=E5=88=A4=E6=96=AD=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=8C=E5=85=A5=E5=BA=93=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=96=B0=E6=A0=87=E7=AD=BE=E7=BC=96=E7=A0=81=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mes/wms/WmOutOrderController.cs | 18 +-- ZR.Common/Tools.cs | 2 - ZR.Service/Utils/MaterialUtils.cs | 143 +++++++++++++++++ .../mes/wms/IService/IWmOutOrderService.cs | 4 +- .../wms/WMentryWarehousing_productService.cs | 7 +- ZR.Service/mes/wms/WmOutOrderService.cs | 149 ++++++++++-------- 6 files changed, 247 insertions(+), 76 deletions(-) create mode 100644 ZR.Service/Utils/MaterialUtils.cs diff --git a/ZR.Admin.WebApi/Controllers/mes/wms/WmOutOrderController.cs b/ZR.Admin.WebApi/Controllers/mes/wms/WmOutOrderController.cs index 7108b450..b1aceef2 100644 --- a/ZR.Admin.WebApi/Controllers/mes/wms/WmOutOrderController.cs +++ b/ZR.Admin.WebApi/Controllers/mes/wms/WmOutOrderController.cs @@ -214,18 +214,18 @@ namespace ZR.Admin.WebApi.Controllers [HttpGet("checkProductionOut")] public IActionResult CheckProductionOut(string production_packcode = "", string shipment_num = "") { - string msg = "可出库"; - if(shipment_num == ""|| production_packcode=="") { - return SUCCESS(null); - - } - bool status=_WmOutOrderService.CheckProductionOut(production_packcode, shipment_num); - if(!status) + string msg = ""; + msg = _WmOutOrderService.CheckProductionOut(production_packcode, shipment_num); + if(msg !="ok") { - msg = "箱子,不在出库单内,不得出库"; + return ToResponse(new ApiResult(200, msg, false)); + } + else + { + return ToResponse(new ApiResult(200, msg, true)); } - return ToResponse(new ApiResult(200, msg, status)); + } } diff --git a/ZR.Common/Tools.cs b/ZR.Common/Tools.cs index c6d4532d..05b40a0e 100644 --- a/ZR.Common/Tools.cs +++ b/ZR.Common/Tools.cs @@ -7,8 +7,6 @@ namespace ZR.Common { public class Tools { - - /// /// 要分割的字符串 eg: 1,3,10,00 /// diff --git a/ZR.Service/Utils/MaterialUtils.cs b/ZR.Service/Utils/MaterialUtils.cs new file mode 100644 index 00000000..b7f9cf5a --- /dev/null +++ b/ZR.Service/Utils/MaterialUtils.cs @@ -0,0 +1,143 @@ +using JinianNet.JNTemplate; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ZR.Model.MES.wms.Dto; +using ZR.Model.MES.wms; + +namespace ZR.Service.Utils +{ + public class MaterialUtils:BaseService + { + private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + //解析外箱标签码 + public ResultionPackageCodeDto ResolutionPackage(string code) + { + // 初步进行解析检测,增加解析成功率 + string[] splitstr = code.Split('^'); + if (splitstr.Length < 1) + { + return null; + } + // 第一类 + if (splitstr[0].Contains("Code=")) + { + return ResolutionPackagecode1(code); + } + // 第二类 + if (splitstr[3].Contains("Cd=")) + { + return ResolutionPackagecode2(code); + } + // 解析失败 + return null; + } + + /// + /// 1-解析鲨鱼鳍外箱标签码 + /// + /// + /// + private ResultionPackageCodeDto ResolutionPackagecode1(string packagecode) + { + ResultionPackageCodeDto resultionPackageCode = new ResultionPackageCodeDto(); + try + { + resultionPackageCode.originalCode = packagecode; + // 解析外箱标签码 + string[] splitstr = packagecode.Split('^'); + // 解析批次号 + resultionPackageCode.PatchCode = splitstr[0].Substring(5); + // 解析零件号 + string partnumber = splitstr[1].Substring(11); + // 有的零件号带了-FL,不是很标准 + resultionPackageCode.PartNumner = partnumber; + // 解析工单号 工单号会带个W,需要去掉 + string workoderidid = splitstr[2].Substring(7); + resultionPackageCode.WorkoderID = workoderidid; + // 解析生产时间 工单号生产时间提取 + resultionPackageCode.ProductionTime = string.Concat("20", workoderidid.AsSpan(0, 6)); + // 解析箱子中产品数量 + string product_num = splitstr[3].Substring(4); + resultionPackageCode.Quantity = int.Parse(product_num); + // 解析产品描述 partnumber 从物料列表抓取数据 + WmMaterial material = Context.Queryable().Where(it => it.Partnumber == partnumber).First(); + if (material == null) + { + resultionPackageCode.ProductionDescribe = "物料记录未录入此零件号信息!"; + return resultionPackageCode; + } + string des1 = material.Description; + string des2 = material.ProductName; + if (string.IsNullOrEmpty(des1)) + { + resultionPackageCode.ProductionDescribe = des1; + } + if (string.IsNullOrEmpty(des2)) + { + resultionPackageCode.ProductionDescribe = des2; + } + return resultionPackageCode; + } + catch (Exception ex) + { + logger.Error($"外箱标签码,解析失败 {ex.Message}"); + return null; + } + } + // 2-解析门把手 + private ResultionPackageCodeDto ResolutionPackagecode2(string packagecode) + { + ResultionPackageCodeDto resultionPackageCode = new ResultionPackageCodeDto(); + try + { + // 原始编码 + resultionPackageCode.originalCode = packagecode; + // 解析外箱标签码 + string[] splitstr = packagecode.Split('^'); + // 解析批次号 + resultionPackageCode.PatchCode = splitstr[3].Substring(3); + // 解析零件号 + string partnumber = splitstr[5].Substring(3); + resultionPackageCode.PartNumner = partnumber; + // 解析工单号 + string workoderidid = splitstr[3].Substring(6, 6); + resultionPackageCode.WorkoderID = workoderidid; + // 生产时间 + resultionPackageCode.ProductionTime = "20" + workoderidid.Substring(0, 6); + //todo 解析箱子中产品数量 + string product_num = splitstr[4].Substring(3); + resultionPackageCode.Quantity = int.Parse(product_num); + // 解析产品描述 partnumber 从物料列表抓取数据 + WmMaterial material = Context.Queryable().Where(it => it.Partnumber == partnumber).First(); + if (material == null) + { + resultionPackageCode.ProductionDescribe = "物料记录未录入此零件号信息!"; + return resultionPackageCode; + } + string des1 = material.Description; + string des2 = material.ProductName; + if (!string.IsNullOrEmpty(des1)) + { + resultionPackageCode.ProductionDescribe = des1; + } + else if (!string.IsNullOrEmpty(des2)) + { + resultionPackageCode.ProductionDescribe = des2; + } + else + { + resultionPackageCode.ProductionDescribe = "物料记录内未填写详情信息!"; + } + return resultionPackageCode; + } + catch (Exception ex) + { + logger.Error($"外箱标签码,解析失败 {ex.Message}"); + return null; + } + } + } +} diff --git a/ZR.Service/mes/wms/IService/IWmOutOrderService.cs b/ZR.Service/mes/wms/IService/IWmOutOrderService.cs index a170a080..84488375 100644 --- a/ZR.Service/mes/wms/IService/IWmOutOrderService.cs +++ b/ZR.Service/mes/wms/IService/IWmOutOrderService.cs @@ -35,7 +35,9 @@ namespace ZR.Service.mes.wms.IService bool OverOutorderplan(string shipment_num); - bool CheckProductionOut(string production_packcode, string shipment_num); + + // 检查是否可出库 + string CheckProductionOut(string production_packcode, string shipment_num); } diff --git a/ZR.Service/mes/wms/WMentryWarehousing_productService.cs b/ZR.Service/mes/wms/WMentryWarehousing_productService.cs index 5e7e7cd4..e580e283 100644 --- a/ZR.Service/mes/wms/WMentryWarehousing_productService.cs +++ b/ZR.Service/mes/wms/WMentryWarehousing_productService.cs @@ -7,6 +7,7 @@ using ZR.Model.MES.pro; using ZR.Model.MES.wms; using ZR.Model.MES.wms.Dto; using ZR.Service.mes.wms.IService; +using ZR.Service.Utils; namespace ZR.Service.mes.wms { @@ -186,7 +187,9 @@ namespace ZR.Service.mes.wms //解析外箱标签码 public ResultionPackageCodeDto ResolutionPackage(string code) { - // 初步进行解析检测,增加解析成功率 + MaterialUtils materialToos = new MaterialUtils(); + return materialToos.ResolutionPackage(code); + /*// 初步进行解析检测,增加解析成功率 string[] splitstr = code.Split('^'); if (splitstr.Length < 1) { @@ -203,7 +206,7 @@ namespace ZR.Service.mes.wms return ResolutionPackagecode2(code); } // 解析失败 - return null; + return null;*/ } diff --git a/ZR.Service/mes/wms/WmOutOrderService.cs b/ZR.Service/mes/wms/WmOutOrderService.cs index 15c3b04d..5dcfe8e8 100644 --- a/ZR.Service/mes/wms/WmOutOrderService.cs +++ b/ZR.Service/mes/wms/WmOutOrderService.cs @@ -13,6 +13,9 @@ using JinianNet.JNTemplate.Dynamic; using System.Linq; using System.Security.Cryptography.Xml; using System.Collections; +using Infrastructure.Model; +using ZR.Service; +using ZR.Service.Utils; namespace ZR.Service.mes.wms { @@ -22,6 +25,8 @@ namespace ZR.Service.mes.wms [AppService(ServiceType = typeof(IWmOutOrderService), ServiceLifetime = LifeTime.Transient)] public class WmOutOrderService : BaseService, IWmOutOrderService { + + /// /// 查询出货单(物料+客户)列表 /// @@ -284,90 +289,72 @@ namespace ZR.Service.mes.wms } /// - /// 生成出货单的出货计划 + /// 生成出库单的出货计划 /// /// 出货单号 /// public List Generate_outorderplan(string shipment_num) { - - List wmOutOrderPlans = new List(); + // 最终结果 + List planList = new List(); // 获取当前出货单下的物料信息 List materialQuery_Prints = this.Queryoutoder_matrials(shipment_num); if (materialQuery_Prints != null && materialQuery_Prints.Count > 0) { - // TODO 1.判断能否完整出货 - - // TODO 2.生成出货单 - + // 物料解析 foreach (var material in materialQuery_Prints) { - //todo 判断要出多少货 按照最早工单和批次号 进行出货(重要算法) - //1. 这个物料要出多少货 + //1. 物料需求量 int require_num = material.RequireOutNum; - // 物料号 string partnumber = material.Partnumber; - // 原始编号 - - // 该物料下 ,现有货物列表 - + // 该物料下 ,现有货物列表,零件号相同,根据批次号从小到大排序 List wmGoodsNowsList = Context.Queryable() .Where(it => it.Partnumber == partnumber) .OrderByDescending(it => it.PackageCodeClient) .ToList(); - // TODO 1.根据入库时间,进行排序 - - // TODO 2.根据排序结果,检查数量是否达标(require_num<=accumulation_num)向最终结果数组进行添加 - List< WmGoodsNowProduction > planList = new List(); - - + // 判断要出多少批次的货 + List wmOutOrderPlans = new List(); foreach (var witem in wmGoodsNowsList) { + // 当前累计批次货物总数 int accumulation_num = 0; if (require_num >= accumulation_num) { WmOutOrderPlan orderPlan = new WmOutOrderPlan(); orderPlan.FkOutOrderId = shipment_num; - orderPlan.Patchcode = witem.PackageCodeClient; + orderPlan.Patchcode_short = witem.PackageCodeClient.Split("_")[0]; orderPlan.MaterialCode = witem.Partnumber; orderPlan.WarehouseCode = witem.LocationCode; - orderPlan.PackageNum = int.Parse(witem.PackageCodeClient.Split("_")[1]); + orderPlan.PackageNum = material.PackageNum; + orderPlan.PartnumberNum = material.ItemNum; orderPlan.RequireNum = require_num; - orderPlan.Patchtime = Resolution_bath(witem.PackageCodeClient); + orderPlan.Patchtime = Resolution_bath(witem.PackageCodeOriginal); wmOutOrderPlans.Add(orderPlan); // 实际值计算 accumulation_num = accumulation_num + witem.GoodsNumAction ?? 0; } - else - { - // 超过要用零头箱 - if (require_num - accumulation_num <= witem.GoodsNumAction) - { - WmOutOrderPlan orderPlan = new WmOutOrderPlan(); - orderPlan.FkOutOrderId = shipment_num; - - orderPlan.Patchcode = witem.PackageCodeClient; - orderPlan.Patchcode_short = witem.PackageCodeClient.Split("_")[0]; - orderPlan.MaterialCode = witem.Partnumber; - orderPlan.WarehouseCode = witem.LocationCode; - orderPlan.PackageNum = 1; //短批次需求累加 - orderPlan.RequireNum = require_num; //总需求 - orderPlan.Patchtime = Resolution_bath(witem.PackageCodeClient); - wmOutOrderPlans.Add(orderPlan); - - accumulation_num = accumulation_num + witem.GoodsNumAction ?? 0; - - } - - break; - } } - - // todo 把该物料下的箱子 按照短批次号 进行分组聚合 - + // 进行聚合 if (wmOutOrderPlans.Count > 0) + { + // 根据批次号下划线前进行聚合 + planList = wmOutOrderPlans.GroupBy(it => it.Patchcode_short).Select(g => new + WmOutOrderPlan + { + FkOutOrderId = g.Max(p => p.FkOutOrderId), + Patchcode = g.Max(p => p.Patchcode), + Patchcode_short = g.Max(p => p.Patchcode_short), + WarehouseCode = g.Max(p => p.WarehouseCode), + MaterialCode = g.Max(p => p.MaterialCode), + PackageNum = g.Count(), + PartnumberNum = g.Max(p => p.PartnumberNum), + RequireNum = g.Max(p => p.RequireNum), + Patchtime = g.Max(p => p.Patchtime), + }).ToList(); + } + /*if (wmOutOrderPlans.Count > 0) { var item = wmOutOrderPlans.GroupBy(it => it.Patchcode_short).Select(g => new { @@ -381,17 +368,21 @@ namespace ZR.Service.mes.wms }); wmOutOrderPlans.Clear(); wmOutOrderPlans.Add(item.Adapt()); - } + }*/ } } - foreach (var witem in wmOutOrderPlans) + // 添加序号 + int count = 1; + foreach (var witem in planList) { - witem.Outorder = wmOutOrderPlans.IndexOf(witem) + 1; + witem.Id = count; + witem.Outorder = count; + count++; } - return wmOutOrderPlans; + return planList; } @@ -463,22 +454,56 @@ namespace ZR.Service.mes.wms /// /// 传入批次号 解析出时间 BNW240318007_105 /// - /// + /// 原始编码 /// - private string Resolution_bath(string bath_code) + private string Resolution_bath(string production_packcode) { - if (string.IsNullOrEmpty(bath_code)) + MaterialUtils materialToos = new MaterialUtils(); + ResultionPackageCodeDto resultionPackage = materialToos.ResolutionPackage(production_packcode); + if (resultionPackage == null) { - return ""; + return "时间解析异常"; } - string temp = bath_code.Split("_")[0]; - return "20" + temp.Substring(2, 6); + return resultionPackage.ProductionTime; } - - public bool CheckProductionOut(string production_packcode, string shipment_num) + /// + /// 检查是否可出库 + /// + /// + /// + /// + public string CheckProductionOut(string production_packcode, string shipment_num) { - + if (shipment_num == "" || production_packcode == "") + { + return "传入数据为空!请检查参数"; + } + MaterialUtils materialToos = new MaterialUtils(); + // 1.解析标签编码 + ResultionPackageCodeDto resultionPackage = materialToos.ResolutionPackage(production_packcode); + if (resultionPackage == null) + { + return "标签解析异常!请检查标签"; + } + // 2.判断是否已入库 + bool isExistedWarehouse = Context.Queryable().Where(it => it.PackageCodeClient == resultionPackage.PatchCode).Any(); + if (!isExistedWarehouse) + { + return "该箱号未入库!请先入库"; + } + // 3.获取出库单号对应的出库计划 + List orderPlans = Generate_outorderplan(shipment_num); + // 4.配对是否符合出库条件 + foreach(var orderPlan in orderPlans) + { + // 存在匹配条件: 箱标签批次号包含计划短批次号 + if(orderPlan != null && resultionPackage.PatchCode.Contains(orderPlan.Patchcode_short) ) + { + return "ok"; + } + } + return "此箱标签不可出库,批次号不在出库单计划内!请检查出库单计划!"; } } } \ No newline at end of file