| | |
| | | throw new Exception("每页条数必须为10、20或50"); |
| | | } |
| | | |
| | | // 1. 查询XB_RACKING_TASK_SYXT_LOG中ItemBarcode和PalletCode的映射关系 |
| | | var allRackingTaskData = Db.Queryable<XbRackingTaskSyxtLog>() |
| | | .Where(x => !string.IsNullOrEmpty(x.ItemBarcode)) |
| | | .Select(x => new { x.ItemBarcode, x.PalletCode, x.Code, x.Id }) |
| | | .ToList(); |
| | | |
| | | // ReturnableStockDto增加一个库存状态的字段 |
| | | // 当allRackingTaskData中的Code为null时,库存状态为立库入库中 |
| | | // 当allRackingTaskData中的Code为200时,库存状态为已经在立库内 |
| | | // 对每个条码,取最新ID的记录,并过滤掉Code为500(表示失败)的记录 |
| | | var rackingTaskData = allRackingTaskData |
| | | .GroupBy(x => x.ItemBarcode) // 按条码分组 |
| | | .Select(g => g.OrderByDescending(x => x.Id).First()) // 取每个条码最新的一条记录 |
| | | .Where(x => x.Code != "500") // 过滤掉Code为500的失败记录 |
| | | .ToList(); |
| | | // 1. 优化:使用原生SQL获取每个条码的最新记录(避免全表加载到内存) |
| | | // 使用窗口函数ROW_NUMBER在数据库层面完成分组取最新记录 |
| | | var sql = @" |
| | | SELECT ITEM_BARCODE, PalletCode, Code, Id |
| | | FROM (SELECT ITEM_BARCODE, |
| | | PalletCode, |
| | | Code, |
| | | Id, |
| | | ROW_NUMBER() OVER (PARTITION BY ITEM_BARCODE ORDER BY Id DESC) as rn |
| | | FROM XB_RACKING_TASK_SYXT_LOG |
| | | WHERE ITEM_BARCODE IS NOT NULL |
| | | AND Code != '500') t |
| | | WHERE rn = 1"; |
| | | |
| | | var rackingTaskData = Db.Ado.SqlQuery<RackingTaskInfo>(sql); |
| | | |
| | | if (rackingTaskData == null || !rackingTaskData.Any()) |
| | | { |
| | |
| | | var distinctBarcodes = rackingTaskData.Select(x => x.ItemBarcode) |
| | | .Distinct().ToList(); |
| | | |
| | | // 2. 构建查询条件 |
| | | var query = Db.Queryable<MesInvItemStocks>() |
| | | .LeftJoin<MesItems>((stock, item) => stock.ItemId == item.Id) |
| | | .LeftJoin<MesDepots>((stock, item, depot) => |
| | | stock.DepotsCode == depot.DepotCode) |
| | | .LeftJoin<Organize>((stock, item, depot, org) => |
| | | item.UseOrg == org.Id.ToString()) |
| | | .LeftJoin<MesUnit>((stock, item, depot, org, unit) => |
| | | item.ItemUnit == unit.Id.ToString()) |
| | | .Where((stock, item, depot, org, unit) => |
| | | (distinctBarcodes.Contains(stock.ItemBarcode) || |
| | | distinctBarcodes.Contains(stock.StackCode)) && |
| | | stock.Quantity > 0); |
| | | |
| | | // 3. 应用搜索条件 |
| | | // 1.2 提取搜索条件(提升作用域) |
| | | var conditions = searchDto.Conditions; |
| | | if (conditions != null) |
| | | |
| | | // 2. 优化:分批处理条码列表(避免IN查询过大) |
| | | const int batchSize = 500; // 每批处理500条 |
| | | var allQueryResults = new List<StockQueryResult>(); |
| | | |
| | | for (int i = 0; i < distinctBarcodes.Count; i += batchSize) |
| | | { |
| | | //当conditions.IqcStatus为1时查询的值就要是特采直接使用,已检,免检,1的值 |
| | | // 精确匹配条件 |
| | | if (!string.IsNullOrEmpty(conditions.IqcStatus)) |
| | | var batchBarcodes = distinctBarcodes.Skip(i).Take(batchSize).ToList(); |
| | | |
| | | // 2.1 构建查询条件 |
| | | var query = Db.Queryable<MesInvItemStocks>() |
| | | .LeftJoin<MesItems>((stock, item) => stock.ItemId == item.Id) |
| | | .LeftJoin<MesDepots>((stock, item, depot) => |
| | | stock.DepotsCode == depot.DepotCode) |
| | | .LeftJoin<Organize>((stock, item, depot, org) => |
| | | item.UseOrg == org.Id.ToString()) |
| | | .LeftJoin<MesUnit>((stock, item, depot, org, unit) => |
| | | item.ItemUnit == unit.Id.ToString()) |
| | | .Where((stock, item, depot, org, unit) => |
| | | (batchBarcodes.Contains(stock.ItemBarcode) || |
| | | batchBarcodes.Contains(stock.StackCode)) && |
| | | stock.Quantity > 0); |
| | | |
| | | // 2.2 应用搜索条件(在数据库层面过滤) |
| | | if (conditions != null) |
| | | { |
| | | if (conditions.IqcStatus == "1") |
| | | //当conditions.IqcStatus为1时查询的值就要是特采直接使用,已检,免检,1的值 |
| | | // 精确匹配条件 |
| | | if (!string.IsNullOrEmpty(conditions.IqcStatus)) |
| | | { |
| | | // 当IqcStatus为"1"时,查询特采直接使用、已检、免检状态 |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.IqcStatus == "特采直接使用" || |
| | | stock.IqcStatus == "已检" || |
| | | stock.IqcStatus == "免检"); |
| | | if (conditions.IqcStatus == "1") |
| | | { |
| | | // 当IqcStatus为"1"时,查询特采直接使用、已检、免检状态 |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.IqcStatus == "特采直接使用" || |
| | | stock.IqcStatus == "已检" || |
| | | stock.IqcStatus == "免检"); |
| | | } |
| | | else |
| | | { |
| | | // 其他情况按原值匹配 |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.IqcStatus == conditions.IqcStatus); |
| | | } |
| | | } |
| | | else |
| | | |
| | | if (conditions.Quantity.HasValue) |
| | | { |
| | | // 其他情况按原值匹配 |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.IqcStatus == conditions.IqcStatus); |
| | | stock.Quantity == conditions.Quantity.Value); |
| | | } |
| | | |
| | | // 模糊匹配条件 |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.DepotName)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | depot.DepotName != null && |
| | | depot.DepotName.Contains(conditions.DepotName)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.DepotSectionsCode)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.DepotSectionsCode != null && |
| | | stock.DepotSectionsCode.Contains(conditions |
| | | .DepotSectionsCode)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemNo)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | item.ItemNo != null && |
| | | item.ItemNo.Contains(conditions.ItemNo)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemName)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | item.ItemName != null && |
| | | item.ItemName.Contains(conditions.ItemName)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemModel)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | item.ItemModel != null && |
| | | item.ItemModel.Contains(conditions.ItemModel)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemUnitName)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | unit.Fname != null && |
| | | unit.Fname.Contains(conditions.ItemUnitName)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.OrgCode)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | org.Fnumber != null && |
| | | org.Fnumber.Contains(conditions.OrgCode)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.OrgName)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | org.Fname != null && |
| | | org.Fname.Contains(conditions.OrgName)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemBarcode)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | (stock.ItemBarcode != null && |
| | | stock.ItemBarcode.Contains(conditions.ItemBarcode)) || |
| | | (stock.StackCode != null && |
| | | stock.StackCode.Contains(conditions.ItemBarcode))); |
| | | } |
| | | |
| | | // 日期范围条件 |
| | | if (!string.IsNullOrEmpty(conditions.IndepDateStart)) |
| | | { |
| | | if (DateTime.TryParse(conditions.IndepDateStart, |
| | | out var startDate)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.IndepDate >= startDate); |
| | | } |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.IndepDateEnd)) |
| | | { |
| | | if (DateTime.TryParse(conditions.IndepDateEnd, out var endDate)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.IndepDate <= endDate); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (conditions.Quantity.HasValue) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.Quantity == conditions.Quantity.Value); |
| | | } |
| | | |
| | | // 模糊匹配条件 |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.DepotName)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | depot.DepotName != null && |
| | | depot.DepotName.Contains(conditions.DepotName)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.DepotSectionsCode)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.DepotSectionsCode != null && |
| | | stock.DepotSectionsCode.Contains(conditions |
| | | .DepotSectionsCode)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemNo)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | item.ItemNo != null && |
| | | item.ItemNo.Contains(conditions.ItemNo)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemName)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | item.ItemName != null && |
| | | item.ItemName.Contains(conditions.ItemName)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemModel)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | item.ItemModel != null && |
| | | item.ItemModel.Contains(conditions.ItemModel)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemUnitName)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | unit.Fname != null && |
| | | unit.Fname.Contains(conditions.ItemUnitName)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.OrgCode)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | org.Fnumber != null && |
| | | org.Fnumber.Contains(conditions.OrgCode)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.OrgName)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | org.Fname != null && |
| | | org.Fname.Contains(conditions.OrgName)); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.ItemBarcode)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.ItemBarcode != null && |
| | | stock.ItemBarcode.Contains(conditions.ItemBarcode)); |
| | | } |
| | | |
| | | // 日期范围条件 |
| | | if (!string.IsNullOrEmpty(conditions.IndepDateStart)) |
| | | { |
| | | if (DateTime.TryParse(conditions.IndepDateStart, |
| | | out var startDate)) |
| | | // 2.3 执行当前批次查询 |
| | | var batchQueryResult = query |
| | | .OrderByDescending((stock, item, depot, org, unit) => |
| | | stock.IndepDate) |
| | | .Select((stock, item, depot, org, unit) => new StockQueryResult |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.IndepDate >= startDate); |
| | | } |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(conditions.IndepDateEnd)) |
| | | { |
| | | if (DateTime.TryParse(conditions.IndepDateEnd, out var endDate)) |
| | | { |
| | | query = query.Where((stock, item, depot, org, unit) => |
| | | stock.IndepDate <= endDate); |
| | | } |
| | | } |
| | | IqcStatus = stock.IqcStatus, |
| | | DepotCode = stock.DepotsCode, |
| | | DepotName = depot.DepotName, |
| | | DepotSectionsCode = stock.DepotSectionsCode, |
| | | ItemNo = item.ItemNo, |
| | | ItemName = item.ItemName, |
| | | ItemModel = item.ItemModel, |
| | | Quantity = stock.Quantity, |
| | | ItemUnit = item.ItemUnit, |
| | | ItemUnitName = unit.Fname, |
| | | IndepDate = stock.IndepDate, |
| | | OrgCode = org.Fnumber, |
| | | OrgName = org.Fname, |
| | | ItemBarcode = stock.ItemBarcode, |
| | | StockStackCode = stock.StackCode |
| | | }) |
| | | .ToList(); |
| | | |
| | | allQueryResults.AddRange(batchQueryResult); |
| | | } |
| | | |
| | | // 3. 合并所有批次的查询结果 |
| | | var queryResult = allQueryResults; |
| | | |
| | | // 4. 查询所有符合条件的数据(不分页) |
| | | var queryResult = query |
| | | .OrderByDescending((stock, item, depot, org, unit) => |
| | | stock.IndepDate) |
| | | .Select((stock, item, depot, org, unit) => new |
| | | { |
| | | stock.IqcStatus, |
| | | DepotCode = stock.DepotsCode, |
| | | depot.DepotName, |
| | | stock.DepotSectionsCode, |
| | | item.ItemNo, |
| | | item.ItemName, |
| | | item.ItemModel, |
| | | stock.Quantity, |
| | | item.ItemUnit, |
| | | ItemUnitName = unit.Fname, |
| | | stock.IndepDate, |
| | | OrgCode = org.Fnumber, |
| | | OrgName = org.Fname, |
| | | stock.ItemBarcode, |
| | | StockStackCode = stock.StackCode |
| | | }) |
| | | .ToList(); |
| | | // 4. 优化:构建条码映射字典(提高查找效率) |
| | | var rackingTaskDict = rackingTaskData |
| | | .ToDictionary(x => x.ItemBarcode, x => x); |
| | | |
| | | // 5. 在内存中转换为DTO,关联PalletCode并赋值ItemBarcode(优先使用箱条码StockStackCode) |
| | | var tempDataList = queryResult.Select(x => |
| | |
| | | var barcodeToMatch = !string.IsNullOrEmpty(x.StockStackCode) |
| | | ? x.StockStackCode |
| | | : x.ItemBarcode; |
| | | var rackingTask = rackingTaskData |
| | | .Where(r => r.ItemBarcode == barcodeToMatch) |
| | | .FirstOrDefault(); |
| | | |
| | | // 使用字典查找,性能更优 |
| | | rackingTaskDict.TryGetValue(barcodeToMatch, out var rackingTask); |
| | | |
| | | // 根据Code值确定库存状态: null为立库入库中(0), 200为已在立库内(1) |
| | | string stockStatus = "进入立库的路上"; // 默认为立库入库中 |
| | | string? stockStatus = "进入立库的路上"; // 默认为立库入库中 |
| | | if (rackingTask?.Code != null) |
| | | { |
| | | stockStatus = rackingTask.Code == "200" ? "已在立库中" : "进入立库的路上"; |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 辅助类:立库任务信息 |
| | | /// </summary> |
| | | private class RackingTaskInfo |
| | | { |
| | | public string? ItemBarcode { get; set; } |
| | | public string? PalletCode { get; set; } |
| | | public string? Code { get; set; } |
| | | public decimal Id { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 辅助类:库存查询中间结果 |
| | | /// </summary> |
| | | private class StockQueryResult |
| | | { |
| | | public string? IqcStatus { get; set; } |
| | | public string? DepotCode { get; set; } |
| | | public string? DepotName { get; set; } |
| | | public string? DepotSectionsCode { get; set; } |
| | | public string? ItemNo { get; set; } |
| | | public string? ItemName { get; set; } |
| | | public string? ItemModel { get; set; } |
| | | public decimal? Quantity { get; set; } |
| | | public string? ItemUnit { get; set; } |
| | | public string? ItemUnitName { get; set; } |
| | | public DateTime? IndepDate { get; set; } |
| | | public string? OrgCode { get; set; } |
| | | public string? OrgName { get; set; } |
| | | public string? ItemBarcode { get; set; } |
| | | public string? StockStackCode { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 查询可以退货的物料(旧版本,保留兼容) |
| | | /// </summary> |
| | | /// <returns>可退货物料库存列表</returns> |
| | |
| | | .FirstOrDefault(); |
| | | |
| | | // 根据Code值确定库存状态: null为立库入库中(0), 200为已在立库内(1) |
| | | string stockStatus = "0"; // 默认为立库入库中 |
| | | string? stockStatus = "0"; // 默认为立库入库中 |
| | | if (rackingTask?.Code != null) |
| | | { |
| | | stockStatus = |
| | |
| | | } |
| | | |
| | | decimal messageId = 0; |
| | | string taskCode = ""; |
| | | string? taskCode = ""; |
| | | |
| | | // 根据条码查询XB_RACKING_TASK_SYXT_LOG表,查询max(PALLETCODE)和对应的widthType |
| | | var rackingTaskInfo = Db.Queryable<XbRackingTaskSyxtLog>() |
| | |
| | | throw new Exception($"解析响应失败: {responseStr}"); |
| | | } |
| | | |
| | | var code = responseJson?.Code?.ToString(); |
| | | var jsonMessage = responseJson?.JsonMessage?.ToString(); |
| | | var code = responseJson?.Code?.ToString()(); |
| | | var jsonMessage = responseJson?.JsonMessage?.ToString()(); |
| | | |
| | | // 7. 根据Code判断成功或失败 |
| | | if (code == "200") |
| | |
| | | ? "任务请求失败" |
| | | : jsonMessage; |
| | | var failureMessage = |
| | | (string)("立库任务下发失败: " + errorMessage); |
| | | (string?)("立库任务下发失败: " + errorMessage); |
| | | |
| | | Db.Updateable<MessageCenter>() |
| | | .SetColumns(it => it.Result == 0) |
| | |
| | | if (messageId > 0) |
| | | { |
| | | var exceptionMessage = |
| | | (string)("立库任务异常: " + ex.Message); |
| | | (string?)("立库任务异常: " + ex.Message); |
| | | Db.Updateable<MessageCenter>() |
| | | .SetColumns(it => it.Result == 0) |
| | | .SetColumns(it => |