WMS仓库-解析箱标签功能提取到MaterialUtils内,入库,出库判断接口优化,入库添加新标签编码解析

This commit is contained in:
赵正易
2024-03-28 11:17:18 +08:00
parent 8bb784a3e5
commit 8e279bdd8a
6 changed files with 247 additions and 76 deletions

View File

@@ -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));
}
}

View File

@@ -7,8 +7,6 @@ namespace ZR.Common
{
public class Tools
{
/// <summary>
/// 要分割的字符串 eg: 1,3,10,00
/// </summary>

View File

@@ -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<WmMaterial>
{
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;
}
/// <summary>
/// 1-解析鲨鱼鳍外箱标签码
/// </summary>
/// <param name="packagecode"></param>
/// <returns></returns>
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<WmMaterial>().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<WmMaterial>().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;
}
}
}
}

View File

@@ -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);
}

View File

@@ -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;*/
}

View File

@@ -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<WmOutOrder>, IWmOutOrderService
{
/// <summary>
/// 查询出货单(物料+客户)列表
/// </summary>
@@ -284,90 +289,72 @@ namespace ZR.Service.mes.wms
}
/// <summary>
/// 生成出单的出货计划
/// 生成出单的出货计划
/// </summary>
/// <param name="shipment_num">出货单号</param>
/// <returns></returns>
public List<WmOutOrderPlan> Generate_outorderplan(string shipment_num)
{
List<WmOutOrderPlan> wmOutOrderPlans = new List<WmOutOrderPlan>();
// 最终结果
List<WmOutOrderPlan> planList = new List<WmOutOrderPlan>();
// 获取当前出货单下的物料信息
List<WmMaterialQuery_print> 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<WmGoodsNowProduction> wmGoodsNowsList = Context.Queryable<WmGoodsNowProduction>()
.Where(it => it.Partnumber == partnumber)
.OrderByDescending(it => it.PackageCodeClient)
.ToList();
// TODO 1.根据入库时间,进行排序
// TODO 2.根据排序结果,检查数量是否达标(require_num<=accumulation_num)向最终结果数组进行添加
List< WmGoodsNowProduction > planList = new List<WmGoodsNowProduction>();
// 判断要出多少批次的货
List<WmOutOrderPlan> wmOutOrderPlans = new List<WmOutOrderPlan>();
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<WmOutOrderPlan>());
}
}*/
}
}
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
/// <summary>
/// 传入批次号 解析出时间 BNW240318007_105
/// </summary>
/// <param name="bath_code"></param>
/// <param name="production_packcode">原始编码</param>
/// <returns></returns>
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)
/// <summary>
/// 检查是否可出库
/// </summary>
/// <param name="production_packcode"></param>
/// <param name="shipment_num"></param>
/// <returns></returns>
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<WmGoodsNowProduction>().Where(it => it.PackageCodeClient == resultionPackage.PatchCode).Any();
if (!isExistedWarehouse)
{
return "该箱号未入库!请先入库";
}
// 3.获取出库单号对应的出库计划
List<WmOutOrderPlan> orderPlans = Generate_outorderplan(shipment_num);
// 4.配对是否符合出库条件
foreach(var orderPlan in orderPlans)
{
// 存在匹配条件: 箱标签批次号包含计划短批次号
if(orderPlan != null && resultionPackage.PatchCode.Contains(orderPlan.Patchcode_short) )
{
return "ok";
}
}
return "此箱标签不可出库,批次号不在出库单计划内!请检查出库单计划!";
}
}
}