using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text.Json; using Infrastructure.Attribute; using MimeKit.Utils; using SqlSugar; using ZR.Model.MES.wms; using ZR.Model.MES.wms.Dto; using ZR.Service.mes.wms.IService; namespace ZR.Service.Business { /// /// 仓库操作日志Service业务层处理 /// [AppService(ServiceType = typeof(IWmGoodsActionService), ServiceLifetime = LifeTime.Transient)] public class WmGoodsActionService : BaseService, IWmGoodsActionService { public WmGoodsChangeLog doConsolidationGoods(WmGoodsConsolidationDto parm) { List list = parm.PackageList; string description = ""; // 拼箱计数器 int num = 0; int? quantityCount = 0; // 第二箱录入数量(限制只能输入两箱) int secondNum = parm.secondNum; int? secondHas = 0; bool isDelete = false; string secondId = ""; // 箱验证 foreach (ResultionPackageCodeDto package in list) { num++; // 有第二箱录入数量的情况下只能两箱拼 if (num == 3) { return null; } WmGoodsNowProduction check1 = Context .Queryable() .Where(it => it.PackageCodeClient == package.PatchCode) .First(); if (check1 == null) { return null; } if (num == 1) { description = "\n主箱:" + package.PatchCode + " 数量:" + package.Quantity + ",\n次箱:"; quantityCount += package.Quantity; continue; } if (num == 2) { secondId = check1.Id; description += package.PatchCode + " 数量:" + package.Quantity + ","; } // 如果PDA所填合并的数量为正数且比次箱子的总数量小 if (num == 2 && secondNum < package.Quantity && secondNum > 0) { isDelete = false; secondHas = package.Quantity - secondNum; quantityCount += secondNum; description += "\n移动数量" + secondNum; } else { isDelete = true; secondHas = 0; quantityCount += package.Quantity; description += "\n移动数量" + package.Quantity; } } ResultionPackageCodeDto mainPackage = list[0]; // 短批次 string shortPatchCode = mainPackage.PatchCode.Split('_')[0]; // 该批次最后一个拼箱记录 WmGoodsNowProduction lastConsolidationPackage = Context .Queryable() .Where(it => it.PackageCodeClient.Contains(shortPatchCode + "_4")) .OrderBy(it => it.PackageCodeClient, OrderByType.Desc) .First(); string newPatchCode = shortPatchCode; // 最终初始编号 int lastCode = 400; // 检测包装是否已打印4XX标签 // 该工单标签最大一个 var packingrecordExp = Expressionable .Create() .And(it => it.WorkOrderNum == mainPackage.WorkoderID) .And(it => it.Machine == "4") .And(it => !it.PackingCode.Contains("Iminate")) .ToExpression(); WmPackingrecord lastPackingrecord = Context .Queryable() .Where(packingrecordExp) .OrderBy(it => it.PackingCode, OrderByType.Desc) .First(); // 优先处理箱打印有历史数据情况 if (lastPackingrecord != null) { int subIndex = lastPackingrecord.PackingCode.Length - 5; // XXX 此代码中 AsSpan 方法 .NET Framework 4.7.2 不支持需要更高版本 或替换为 Substring if ( int.TryParse( lastPackingrecord.PackingCode.AsSpan(subIndex).TrimStart('0'), out int lastPackingrecordCode ) ) { if (lastPackingrecordCode > lastCode) { lastCode = lastPackingrecordCode; } } else { throw new Exception("生成标签数据异常:" + lastPackingrecord.PackingCode); } } // 其次处理成品库历史最大数字 if (lastConsolidationPackage != null) { if ( int.TryParse( lastConsolidationPackage.PackageCodeClient.Split('_')[1], out int lastConsolidationPackageCode ) ) { // 取最大值 if (lastConsolidationPackageCode > lastCode) { lastCode = lastConsolidationPackageCode; } } else { throw new Exception("生成标签数据异常:" + lastConsolidationPackage.PackageCodeClient); } } if (lastCode > 400) { newPatchCode += "_" + (lastCode + 1); } else { newPatchCode += "_401"; } description += "\n拼箱结果:" + newPatchCode + " 总数量:" + quantityCount; DateTime nowTime = DateTime.Now.ToLocalTime(); var jsonObject = new { packageList = list, // 拼箱批次号 newPatchCode = newPatchCode, // 拼箱流水号 serialNumber = newPatchCode.Split("_")[1], // 拼箱数量 newQuantityCount = quantityCount, // 拼箱班组 Team = "C", // 拼箱零件号 newPartnumber = mainPackage.PartNumner, // 拼箱时间 time = DateUtils.FormatDate(nowTime) }; // 日志记录 WmGoodsChangeLog log = new() { CreatedBy = parm.CreateBy, CreatedTime = nowTime, Description = description, JsonMsg = JsonSerializer.Serialize(jsonObject), Type = 1 }; Context.Insertable(log).ExecuteReturnEntity(); // 执行修改 // 1.主箱查出并修改参数 WmGoodsNowProduction nowProduction = Context .Queryable() .Where(it => it.PackageCodeClient == mainPackage.PatchCode) .First(); if (nowProduction == null) { return null; } nowProduction.UpdatedBy = parm.CreateBy; nowProduction.UpdatedTime = nowTime; nowProduction.PackageCodeClient = newPatchCode; nowProduction.PackageCodeOriginal = "Code=" + newPatchCode + "^ItemNumber=" + nowProduction.Partnumber + "^Order=" + newPatchCode.Split('_')[0].Substring(2) + "^Qty=" + quantityCount; nowProduction.GoodsNumLogic = quantityCount; nowProduction.GoodsNumAction = quantityCount; nowProduction.Remark = "拼箱整箱"; //TODO 20240422开会讨论结果:拼箱完需要重新扫码入库,原数据删除 Context .Deleteable() .Where(it => it.Id == nowProduction.Id) .ExecuteCommand(); Context .Deleteable() .Where(it => it.Id == secondId) .ExecuteCommand(); //TODO 20240510添加标签记录信息到标签记录信息表 try { Context.Ado.BeginTran(); WmPackageLcl mainPackageLcl = new() { Id = SnowFlakeSingle.instance.NextId().ToString(), Partnumber = nowProduction.Partnumber, WorkOrderId = newPatchCode.Substring(3, 9), PackageCode = newPatchCode, SerialNumber = newPatchCode.Split('_')[1], LocationCode = nowProduction.LocationCode, GoodsNum = nowProduction.GoodsNumAction ?? 0, Team = "C", Type = 1, Status = 0, CreatedBy = "拼箱", CreatedTime = nowTime, Remark = "拼箱整箱" }; Context.Insertable(mainPackageLcl).ExecuteCommand(); if (!isDelete) { WmPackageLcl oddPackageLcl = new() { Id = SnowFlakeSingle.instance.NextId().ToString(), Partnumber = list[1].PartNumner, WorkOrderId = list[1].PatchCode.Substring(3, 9), PackageCode = list[1].PatchCode, SerialNumber = list[1].PatchCode.Split('_')[1], LocationCode = "LS", GoodsNum = secondHas ?? 0, Team = "C", Type = 1, Status = 0, CreatedBy = "拼箱", CreatedTime = nowTime, Remark = "拼箱零头箱" }; Context.Insertable(oddPackageLcl).ExecuteCommand(); } Context.Ado.CommitTran(); return log; } catch (Exception ex) { Context.Ado.RollbackTran(); throw new Exception("生成打印标签信息异常!" + ex); } return log; // 修改主箱 Context .Updateable(nowProduction) .IgnoreColumns(ignoreAllNullColumns: true) .ExecuteCommand(); // 次箱操作 if (isDelete) { // 删除次箱 Context .Deleteable() .Where(it => it.Id == secondId) .ExecuteCommand(); } else { // 修改次箱子 WmGoodsNowProduction nowProduction2 = Context .Queryable() .Where(it => it.Id == secondId) .First(); if (nowProduction2 == null) { return null; } nowProduction2.UpdatedBy = parm.CreateBy; nowProduction2.UpdatedTime = nowTime; nowProduction2.PackageCodeOriginal = "Code=" + nowProduction2.PackageCodeClient + "^ItemNumber=" + nowProduction2.Partnumber + "^Order=" + nowProduction2.PackageCodeClient.Split('_')[0].Substring(2) + "^Qty=" + secondHas; nowProduction2.GoodsNumLogic = secondHas; nowProduction2.GoodsNumAction = secondHas; nowProduction2.LocationCode = "LS"; nowProduction2.Remark = "拼箱零头箱"; Context .Updateable(nowProduction2) .IgnoreColumns(ignoreAllNullColumns: true) .ExecuteCommand(); } return log; } public WmGoodsChangeLog doUnpackingGoods(WmGoodsUnpackingDto parm) { string description = ""; // 待拆箱 ResultionPackageCodeDto mainPackage = parm.Package; // 验证 WmGoodsNowProduction mainNowProduction = Context .Queryable() .Where(it => it.PackageCodeClient == mainPackage.PatchCode) .First(); if (mainNowProduction == null) { return null; } description += "\n由主箱:" + mainPackage.PatchCode + " 数量:" + mainPackage.Quantity + "拆分:"; // 短批次 string shortPatchCode = mainPackage.PatchCode.Split('_')[0]; // 该批次最后一个拼箱记录 WmGoodsNowProduction lastConsolidationPackage = Context .Queryable() .Where(it => it.PackageCodeClient.Contains(shortPatchCode + "_4")) .OrderBy(it => it.PackageCodeClient, OrderByType.Desc) .First(); string newPatchCode1 = shortPatchCode; string newPatchCode2 = shortPatchCode; // 检测包装是否已打印4XX标签 // 该工单标签最大一个 var packingrecordExp = Expressionable .Create() .And(it => it.WorkOrderNum == mainPackage.WorkoderID) .And(it => it.Machine == "4") .And(it => !it.PackingCode.Contains("Iminate")) .ToExpression(); WmPackingrecord lastPackingrecord = Context .Queryable() .Where(packingrecordExp) .OrderBy(it => it.PackingCode, OrderByType.Desc) .First(); int lastCode = 400; // 优先处理箱打印有历史数据情况 if (lastPackingrecord != null) { int subIndex = lastPackingrecord.PackingCode.Length - 5; // XXX 此代码中 AsSpan 方法 .NET Framework 4.7.2 不支持需要更高版本 或替换为 Substring if ( int.TryParse( lastPackingrecord.PackingCode.AsSpan(subIndex).TrimStart('0'), out int lastPackingrecordCode ) ) { if (lastPackingrecordCode > lastCode) { lastCode = lastPackingrecordCode; } } else { throw new Exception("生成标签数据异常:" + lastPackingrecord.PackingCode); } } if (lastConsolidationPackage != null) { if ( int.TryParse( lastConsolidationPackage.PackageCodeClient.Split('_')[1], out int lastConsolidationPackageCode ) ) { if (lastConsolidationPackageCode > lastCode) { lastCode = lastConsolidationPackageCode; } } else { throw new Exception("生成标签数据异常:" + lastConsolidationPackage.PackageCodeClient); } } if (lastCode > 400) { newPatchCode1 += "_" + (lastCode + 1); newPatchCode2 += "_" + (lastCode + 2); } else { newPatchCode1 += "_401"; newPatchCode2 += "_402"; } int firstNum = parm.firstNum; int? secondNum = mainNowProduction.GoodsNumAction - firstNum; if (secondNum <= 0) { return null; } description += "\n拆箱结果1:" + newPatchCode1 + "数量为" + firstNum + "个"; description += "\n拆箱结果2:" + newPatchCode2 + "数量为" + secondNum + "个"; DateTime nowTime = DateTime.Now.ToLocalTime(); var jsonObject = new { // 主箱信息 mainPackage = mainPackage, // 新标签1 newPatchCode1 = newPatchCode1, // 新流水号1 serialNumber1 = newPatchCode1.Split("_")[1], // 新标签2 newPatchCode2 = newPatchCode2, // 新流水号2 serialNumber2 = newPatchCode2.Split("_")[1], // 拆箱1数量 firstNum = firstNum, // 拆箱2数量 secondNum = secondNum, // 班组 Team = "C", // 全部箱子零件号 newPartnumber = mainPackage.PartNumner, // 拆箱时间 time = DateUtils.FormatDate(nowTime) }; // 日志记录 WmGoodsChangeLog log = new() { CreatedBy = parm.CreateBy, CreatedTime = nowTime, Description = description, JsonMsg = JsonSerializer.Serialize(jsonObject), Type = 2 }; Context.Insertable(log).ExecuteReturnEntity(); //TODO 20240422开会讨论结果:拆箱完需要重新扫码入库,原主箱数据删除 Context .Deleteable() .Where(it => it.Id == mainNowProduction.Id) .ExecuteCommand(); //TODO 20240510 添加待打印的记录 try { Context.Ado.BeginTran(); WmPackageLcl packageLcl1 = new() { Id = SnowFlakeSingle.instance.NextId().ToString(), Partnumber = mainNowProduction.Partnumber, WorkOrderId = jsonObject.newPatchCode1.Substring(3, 9), PackageCode = jsonObject.newPatchCode1, SerialNumber = jsonObject.serialNumber1, LocationCode = mainNowProduction.LocationCode, GoodsNum = jsonObject.firstNum, Team = "C", Type = 2, Status = 0, CreatedBy = "拆箱", CreatedTime = nowTime, Remark = "拆箱1" }; Context.Insertable(packageLcl1).ExecuteCommand(); WmPackageLcl packageLcl2 = new() { Id = SnowFlakeSingle.instance.NextId().ToString(), Partnumber = mainNowProduction.Partnumber, WorkOrderId = jsonObject.newPatchCode2.Substring(3, 9), PackageCode = jsonObject.newPatchCode2, SerialNumber = jsonObject.serialNumber2, LocationCode = "LS", GoodsNum = jsonObject.secondNum ?? 0, Team = "C", Type = 2, Status = 0, CreatedBy = "拆箱", CreatedTime = nowTime, Remark = "拆箱2" }; Context.Insertable(packageLcl2).ExecuteCommand(); Context.Ado.CommitTran(); return log; } catch (Exception ex) { Context.Ado.RollbackTran(); throw new Exception("生成打印标签信息异常!" + ex); } return log; // 执行修改 // 1.主箱修改为1号分箱参数 WmGoodsNowProduction newPackage1 = mainNowProduction; newPackage1.UpdatedBy = parm.CreateBy; newPackage1.UpdatedTime = nowTime; newPackage1.PackageCodeClient = newPatchCode1; newPackage1.PackageCodeOriginal = "Code=" + newPatchCode1 + "^ItemNumber=" + newPackage1.Partnumber + "^Order=" + newPatchCode1.Split('_')[0].Substring(2) + "^Qty=" + firstNum; newPackage1.GoodsNumLogic = firstNum; newPackage1.GoodsNumAction = firstNum; newPackage1.Remark = "拆箱"; // 修改主箱 Context .Updateable(newPackage1) .IgnoreColumns(ignoreAllNullColumns: true) .ExecuteCommand(); // 2.添加一个分箱 WmGoodsNowProduction newPackage2 = mainNowProduction; newPackage2.CreatedBy = parm.CreateBy; newPackage2.CreatedTime = nowTime; newPackage2.PackageCodeClient = newPatchCode2; newPackage2.PackageCodeOriginal = "Code=" + newPatchCode2 + "^ItemNumber=" + newPackage2.Partnumber + "^Order=" + newPatchCode2.Split('_')[0].Substring(2) + "^Qty=" + secondNum; newPackage2.GoodsNumLogic = secondNum; newPackage2.GoodsNumAction = secondNum; newPackage2.Remark = "拆箱"; newPackage2.Id = SnowFlakeSingle.Instance.NextId().ToString(); // 添加分箱 Context.Insertable(newPackage2).ExecuteCommand(); return log; } // 添加包装箱标签记录(暂不使用) public void AddPackingrecord( WmGoodsNowProduction production, string workOrderId, bool isFill = false ) { try { if (int.TryParse(production.PackageCodeClient.Split('_')[1], out int packageNum)) { WmPackingrecord packingrecord = new() { PartNum = production.Partnumber, Machine = "4", ProductCode = "Iminate_P_0", PackingCode = workOrderId + packageNum.ToString("00000"), ScannerContent = production.PackageCodeOriginal, WorkOrderNum = workOrderId, BFilled = isFill, CreateTime = DateTime.Now, }; Context.Insertable(packingrecord).ExecuteCommand(); } else { throw new Exception("包装箱标签批次号数量解析失败!"); } } catch (Exception ex) { throw new Exception("包装箱标签插入失败!" + ex); } } public WmGoodsChangeLog DoConsolidationGoods2(WmGoodsConsolidationDto2 parm) { Context.Ado.BeginTran(); try { List packageList = parm.PackageList; if (packageList.Count < 2) { throw new Exception("至少需要两箱才能拼箱!"); } //提出主箱 ResultionPackageCodeDto mainPackage = packageList[0] ?? throw new Exception("主箱信息异常!"); int mainPackageActionNum = parm.MainPackageActionNum; // 结果数判定 if (mainPackageActionNum < mainPackage.Quantity) { throw new Exception("主箱最终零件数需要大于原零件数!"); } // 拼箱下标计数器 int index = 0; // 拼箱结果 string description = ""; // 最终结果总零件数 int quantityCount = 0; // 主箱最终新标签 string newMainPackageCode = ""; foreach (ResultionPackageCodeDto package in packageList) { index++; // 箱数据 int packageQuantity = package.Quantity ?? 0; string patchCode = package.PatchCode ?? ""; // 验证箱 WmGoodsNowProduction wmGoodsNowProduction = Context .Queryable() .Where(it => it.PackageCodeClient == patchCode) .First(); if (wmGoodsNowProduction == null) { throw new Exception("该箱不在库存中!批次号:" + patchCode); } // 第一箱 if (index == 1) { description = "\n主箱:" + patchCode + "\n原数量:" + packageQuantity; quantityCount += packageQuantity; newMainPackageCode = GetNewPackageCode(package); // 添加打印记录 AddWmPackageLcl( 1, newMainPackageCode, wmGoodsNowProduction, mainPackageActionNum, parm.CreateBy ); // 删除数据 Context .Deleteable() .Where(it => it.PackageCodeClient == patchCode) .ExecuteCommand(); continue; } // 已拼完 if (quantityCount >= mainPackageActionNum) { break; } // 未拼完 // 删除数据 Context .Deleteable() .Where(it => it.PackageCodeClient == patchCode) .ExecuteCommand(); if (packageQuantity + quantityCount < mainPackageActionNum) { //1.还没够 description += "\n次箱:" + patchCode + "\n原数量:" + packageQuantity; description += "\n移动数量:" + packageQuantity; quantityCount += packageQuantity; } // 拼完了 else if (packageQuantity + quantityCount == mainPackageActionNum) { //2.刚刚好 description += "\n次箱:" + patchCode + "\n原数量:" + packageQuantity; description += "\n移动数量:" + packageQuantity; quantityCount += packageQuantity; break; } else if (packageQuantity + quantityCount > mainPackageActionNum) { //3.超额了 int surplus = mainPackageActionNum - quantityCount; description += "\n次箱:" + patchCode + "\n原数量:" + packageQuantity; description += "\n移动数量" + surplus; quantityCount = mainPackageActionNum; // 添加记录 string newPackageCode = GetNewPackageCode(package); AddWmPackageLcl( 1, newPackageCode, wmGoodsNowProduction, (package.Quantity - surplus) ?? 0, parm.CreateBy ); break; } } description += "\n拼箱结果:" + newMainPackageCode + "\n总数量:" + quantityCount; DateTime nowTime = DateTime.Now.ToLocalTime(); var jsonObject = new { packageList, // 拼箱批次号 newPatchCode = newMainPackageCode, // 拼箱流水号 serialNumber = newMainPackageCode.Split("_")[1], // 拼箱数量 newQuantityCount = quantityCount, // 拼箱班组 Team = "C", // 拼箱零件号 newPartnumber = mainPackage.PartNumner, // 拼箱时间 time = DateUtils.FormatDate(nowTime) }; // 日志记录 WmGoodsChangeLog log = new() { CreatedBy = parm.CreateBy, CreatedTime = nowTime, Description = description, JsonMsg = JsonSerializer.Serialize(jsonObject), Type = 1 }; Context.Insertable(log).ExecuteReturnEntity(); Context.Ado.CommitTran(); return log; } catch (Exception ex) { Context.Ado.RollbackTran(); throw new Exception(ex.Message); } } /// /// 添加包装箱标签打印记录 /// /// 类别 1-拼箱 2-拆箱 /// 新标签 /// 旧箱数据 /// 待打印零件数 /// 执行人 /// public void AddWmPackageLcl( int type, string newPackageCode, WmGoodsNowProduction oldPackageInfo, int GoodsNum, string createdBy ) { try { WmPackageLcl packageLcl = new() { Id = SnowFlakeSingle.instance.NextId().ToString(), Partnumber = oldPackageInfo.Partnumber, WorkOrderId = oldPackageInfo.PackageCodeClient.Substring(3, 9), PackageCode = newPackageCode, SerialNumber = newPackageCode.Split('_')[1] ?? "500", LocationCode = "LS", GoodsNum = GoodsNum, Team = "C", Type = 1, Status = 0, CreatedBy = createdBy, CreatedTime = DateTime.Now.ToLocalTime(), Remark = type == 1 ? "PDA拼箱" : "PDA拆箱" }; Context.Insertable(packageLcl).ExecuteCommand(); } catch (Exception ex) { throw new Exception("包装箱标签打印记录插入失败!" + ex); } } public string GetNewPackageCode(ResultionPackageCodeDto resultionPackageCode) { try { string shortPatchCode = resultionPackageCode.PatchCode.Split('_')[0]; // 该批次最后一个拼箱记录 WmGoodsNowProduction lastConsolidationPackage = Context .Queryable() .Where(it => it.PackageCodeClient.Contains(shortPatchCode + "_4")) .OrderBy(it => it.PackageCodeClient, OrderByType.Desc) .First(); string newPatchCode = shortPatchCode; // 最终初始编号 int lastCode = 400; // 检测包装是否已打印4XX标签 // 该工单标签最大一个 var packingrecordExp = Expressionable .Create() .And(it => it.WorkOrderNum == resultionPackageCode.WorkoderID) .And(it => it.Machine == "4") .And(it => !it.PackingCode.Contains("Iminate")) .ToExpression(); WmPackingrecord lastPackingrecord = Context .Queryable() .Where(packingrecordExp) .OrderBy(it => it.PackingCode, OrderByType.Desc) .First(); // 优先处理箱打印有历史数据情况 if (lastPackingrecord != null) { int subIndex = lastPackingrecord.PackingCode.Length - 5; // XXX 此代码中 AsSpan 方法 .NET Framework 4.7.2 不支持需要更高版本 或替换为 Substring if ( int.TryParse( lastPackingrecord.PackingCode.AsSpan(subIndex).TrimStart('0'), out int lastPackingrecordCode ) ) { if (lastPackingrecordCode > lastCode) { lastCode = lastPackingrecordCode; } } else { throw new Exception("生成标签数据异常:" + lastPackingrecord.PackingCode); } } // 其次处理成品库历史最大数字 if (lastConsolidationPackage != null) { if ( int.TryParse( lastConsolidationPackage.PackageCodeClient.Split('_')[1], out int lastConsolidationPackageCode ) ) { // 取最大值 if (lastConsolidationPackageCode > lastCode) { lastCode = lastConsolidationPackageCode; } } else { throw new Exception( "生成新标签数据异常:" + lastConsolidationPackage.PackageCodeClient ); } } if (lastCode > 400) { newPatchCode += "_" + (lastCode + 1); } else { newPatchCode += "_401"; } return newPatchCode; } catch (Exception ex) { throw new Exception("生成新标签失败!" + ex); } } } }