diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsCheckTaskService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsCheckTaskService.cs index 3d4abb02..951f5ab0 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WmsCheckTaskService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsCheckTaskService.cs @@ -13,6 +13,7 @@ using JNPF.VisualDev.Interfaces; using Mapster; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json.Linq; +using NPOI.SS.Formula.Functions; using SqlSugar; using Tnb.BasicData.Entities; using Tnb.WarehouseMgr.Entities; @@ -29,7 +30,7 @@ namespace Tnb.WarehouseMgr /// 盘点任务 /// [OverideVisualDev(ModuleConsts.MODULE_WMSCHECKTASK_ID)] - public class WmsCheckTaskService : BaseWareHouseService + public class WmsCheckTaskService : BaseWareHouseService { private readonly ISqlSugarClient _db; private readonly IWareHouseService _warehouseService; @@ -99,39 +100,49 @@ namespace Tnb.WarehouseMgr } VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(ModuleConsts.MODULE_WMSCHECKTASK_ID, true); await _runService.Create(templateEntity, input); - List carryCodes = new(); List details = new(); - switch (checkType!.ToEnum()) + var filterExpable = Expressionable.Create() + .And((a, b, c) => a.wh_id == input.data[nameof(WmsCheckstockH.warehouse_id)].ToString()) + .And((a, b, c) => a.is_type == ((int)EnumLocationType.存储库位).ToString()) + .And((a, b, c) => c.is_lock == 0); + + var areaIds = new string[] { }; + if (input.data.ContainsKey(nameof(WmsCheckstockH.area_id)) && input.data[nameof(WmsCheckstockH.area_id)] != null) { - case EnumCheckType.全库盘点: - carryCodes = await _db.Queryable().InnerJoin((a, b) => a.id == b.location_id) - .Where(a => a.wh_id == input.data[nameof(WmsCheckstockH.warehouse_id)].ToString() && a.is_type == ((int)EnumLocationType.存储库位).ToString()) - .Select() - .ToListAsync(); - carryCodes ??= Enumerable.Empty().ToList(); - List? checkStockDs = carryCodes.Adapt>(); - var prQtyDic = checkStockDs.GroupBy(g => new { g.carry_id, g.material_id, g.code_batch }).ToDictionary(x => x.Key, x => x.Sum(d => d.codeqty)); - - foreach ((object k, decimal v) in prQtyDic) - { - WmsCheckstockD? checkstockD = checkStockDs?.Find(x => string.Equals(k, $"{x.carry_id}{x.material_id}{x.code_batch}")); - if (checkstockD != null) - { - checkstockD.id = SnowflakeIdHelper.NextId(); - checkstockD.create_id = _userManager.UserId; - checkstockD.create_time = DateTime.Now; - checkstockD.pr_qty = v; - details.Add(checkstockD); - } - } - _ = await _db.Insertable(details).ExecuteCommandAsync(); - break; - case EnumCheckType.物料盘点: - - break; - case EnumCheckType.批次盘点: - break; + areaIds = input.data[nameof(WmsCheckstockH.area_id)].ToObject(); } + + filterExpable = checkType!.ToEnum() switch + { + EnumCheckType.物料盘点 => filterExpable.AndIF(input.data.ContainsKey(nameof(WmsCarryCode.material_id)) && input.data[nameof(WmsCarryCode.material_id)] != null, (a, b, c) => b.material_id == input.data[nameof(WmsCarryCode.material_id)].ToString()), + EnumCheckType.批次盘点 => filterExpable.AndIF(areaIds?.Length > 0, (a, b, c) => areaIds.Contains(a.region_id)), + _ => filterExpable, + }; + + var carryCodes = await _db.Queryable().InnerJoin((a, b) => a.id == b.location_id) + .InnerJoin((a, b, c) => b.carry_id == c.id) + .Where(filterExpable.ToExpression()) + .Select() + .ToListAsync(); + + carryCodes ??= Enumerable.Empty().ToList(); + List? checkStockDs = carryCodes.Adapt>(); + var prQtyDic = checkStockDs.GroupBy(g => $"{g.carry_id}{g.material_id}{g.code_batch}").ToDictionary(x => x.Key, x => x.Sum(d => d.codeqty)); + + foreach ((object k, decimal v) in prQtyDic) + { + WmsCheckstockD? checkstockD = checkStockDs?.Find(x => string.Equals(k, $"{x.carry_id}{x.material_id}{x.code_batch}")); + if (checkstockD != null) + { + checkstockD.id = SnowflakeIdHelper.NextId(); + checkstockD.checkstock_id = input.data["ReturnIdentity"].ToString(); + checkstockD.create_id = _userManager.UserId; + checkstockD.create_time = DateTime.Now; + checkstockD.pr_qty = v; + details.Add(checkstockD); + } + } + _ = await _db.Insertable(details).ExecuteCommandAsync(); //生成预任务信息 if (details.Count > 0 && carryCodes.Count > 0) { @@ -142,7 +153,7 @@ namespace Tnb.WarehouseMgr int randomIndex = 0; if (wcsConf != null) { - if (wcsConf.location_id == null) + if (wcsConf.location_id.IsNullOrWhiteSpace()) { throw new AppFriendlyException("盘点签收配置库位为空,请查看配置!", 500); } @@ -152,7 +163,7 @@ namespace Tnb.WarehouseMgr if (locArr != null) { endLocs = await _db.Queryable().Where(it => it.wh_id == input.data[nameof(WmsCheckstockH.warehouse_id)].ToString() && locArr.Contains(it.id)).ToArrayAsync(); - randomIndex = new Random().Next(0, endLocs.GetUpperBound(0)); + randomIndex = Random.Shared.Next(0, endLocs.GetUpperBound(0)); } else { @@ -164,7 +175,7 @@ namespace Tnb.WarehouseMgr { string[] locTypes = new[] { ((int)EnumLocationType.出库库位).ToString(), ((int)EnumLocationType.出入库位).ToString() }; endLocs = await _db.Queryable().Where(it => it.wh_id == input.data[nameof(WmsCheckstockH.warehouse_id)].ToString() && locTypes.Contains(it.is_type)).ToArrayAsync(); - randomIndex = new Random().Next(0, endLocs.GetUpperBound(0)); + randomIndex = Random.Shared.Next(0, endLocs.GetUpperBound(0)); } List carrys = await _db.Queryable().Where(it => carryCodes.Select(x => x.carry_id).Distinct().Contains(it.id)).ToListAsync(); @@ -243,7 +254,7 @@ namespace Tnb.WarehouseMgr bool isOk = await _warehouseService.GenPreTask(preTasks, pretaskCodes); if (isOk) { - _ = await _db.Updateable().SetColumns(it => it.status == ((int)EnumCheckStatus.盘点中).ToString()).ExecuteCommandAsync(); + _ = await _db.Updateable().SetColumns(it => it.status == ((int)EnumCheckStatus.盘点中).ToString()).Where(it => it.id == input.data["ReturnIdentity"].ToString()).ExecuteCommandAsync(); GenPreTaskUpInput genPreTaskAfterUpInput = new() { CarryIds = preTasks.Select(x => x.carry_id).ToList(), @@ -258,9 +269,10 @@ namespace Tnb.WarehouseMgr await _db.Ado.CommitTranAsync(); } - catch (Exception) + catch (Exception ex) { row = 0; + Logger.Error("盘点任务新增失败", ex); await _db.Ado.RollbackTranAsync(); throw; } @@ -276,6 +288,18 @@ namespace Tnb.WarehouseMgr return _db.CopyNew().Queryable().InnerJoin(joinExp).Where(whereExp).Select().ToListAsync(); } + /// + /// 根据盘点任务ID获取盘点任务明细 + /// + /// + /// + [HttpGet("checkStockId")] + public async Task> GetCheckStockDList(string checkStockId) + { + return await _db.Queryable().Where(it => it.checkstock_id == checkStockId).ToListAsync(); + } + + /// /// 根据盘点类型获取任务明细 /// @@ -296,19 +320,38 @@ namespace Tnb.WarehouseMgr _carryMap = await _db.Queryable().ToDictionaryAsync(x => x.id, x => x.carry_code); } - var filterExpable = Expressionable.Create() - .And((a, b, c) => a.wh_id == input.warehouse_id) - .And((a, b, c) => a.is_type == ((int)EnumLocationType.存储库位).ToString()) - .And((a, b, c) => c.is_lock == 0); - filterExpable = input.CheckType switch + //var filterExpable = Expressionable.Create(); + Expression> filterExp = (a, b, c) => false; + switch (input.CheckType) { - EnumCheckType.物料盘点 => filterExpable.AndIF(!string.IsNullOrEmpty(input.material_id), (a, b, c) => b.material_id == input.material_id), - EnumCheckType.批次盘点 => filterExpable.AndIF(input.regionIds?.Count > 0, (a, b, c) => input.regionIds.Contains(a.region_id)), - _ => filterExpable, - }; + case EnumCheckType.全库盘点: + { + filterExp.And((a, b, c) => a.wh_id == input.warehouse_id) + .And((a, b, c) => a.is_type == ((int)EnumLocationType.存储库位).ToString()) + .And((a, b, c) => c.is_lock == 0); + } + break; + case EnumCheckType.物料盘点: + { + if (!input.material_id.IsNullOrWhiteSpace()) + { + filterExp.And((a, b, c) => b.material_id == input.material_id); + } + } + break; + case EnumCheckType.批次盘点: + { + if (input.regionIds?.Count > 0) + { + filterExp.And((a, b, c) => input.regionIds.Contains(a.region_id)); + } + } + break; + } + var carryCodes = await _db.Queryable().InnerJoin((a, b) => a.id == b.location_id) .InnerJoin((a, b, c) => b.carry_id == c.id) - .Where(filterExpable.ToExpression()) + .Where(filterExp) .Select() .ToListAsync(); diff --git a/common/Tnb.Common/Extension/LambdaExpressionExtensions.cs b/common/Tnb.Common/Extension/LambdaExpressionExtensions.cs index a87f09b4..b0b1b420 100644 --- a/common/Tnb.Common/Extension/LambdaExpressionExtensions.cs +++ b/common/Tnb.Common/Extension/LambdaExpressionExtensions.cs @@ -23,8 +23,81 @@ namespace JNPF.Common.Extension } setAction(instance, value); } + + /// + /// Lambda表达式拼接 + /// + /// + /// + /// + /// + /// + public static Expression> Compose(this Expression> first, Expression> second, + Func merge) + { + // build parameter map (from parameters of second to parameters of first) + var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); + // replace parameters in the second lambda expression with parameters from the first + var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); + // apply composition of lambda expression bodies to parameters from the first expression + return Expression.Lambda>(merge(first.Body, secondBody), first.Parameters); + } + /// + /// and扩展 + /// + /// + /// + /// + /// + public static Expression> And(this Expression> first, Expression> second) + { + if (first.IsNull()) + { + first = second; + return first; + } + + return first.Compose(second, Expression.And); + } } + + public class ParameterRebinder : ExpressionVisitor + { + private readonly Dictionary map; + /// + /// + /// + /// + public ParameterRebinder(Dictionary map) + { + this.map = map ?? new Dictionary(); + } + /// + /// + /// + /// + /// + /// + public static Expression ReplaceParameters(Dictionary map, Expression exp) + { + return new ParameterRebinder(map).Visit(exp); + } + /// + /// + /// + /// + /// + protected override Expression VisitParameter(ParameterExpression p) + { + ParameterExpression replacement; + if (map.TryGetValue(p, out replacement)) + { + p = replacement; + } + return base.VisitParameter(p); + } + } public class PropertySet { public static Dictionary> ValueFactories = new Dictionary>(StringComparer.OrdinalIgnoreCase);