11
tjx
2 天以前 fb6414b4ee8ba0d65c037536da5d02eff24f60d0
StandardPda/MES.Service/service/Warehouse/MesInvItemStocksManager.cs
@@ -26,9 +26,9 @@
        // 优化点1: 使用原生SQL ROW_NUMBER()在数据库端完成去重和排序
        var rackingTaskSql = @"
            SELECT ITEM_BARCODE AS ItemBarcode, PALLETCODE AS PalletCode, CODE AS Code
            SELECT ITEM_BARCODE AS ItemBarcode, PALLETCODE AS PalletCode, CODE AS Code, TASKTYPE AS TaskType
            FROM (
                SELECT ITEM_BARCODE, PALLETCODE, CODE,
                SELECT ITEM_BARCODE, PALLETCODE, CODE, TASKTYPE,
                       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 IS NULL OR CODE != '500')
@@ -204,6 +204,7 @@
            .Select((stock, item, depot, org, unit) => new
            {
                stock.IqcStatus,
                stock.Visible,
                DepotCode = stock.DepotsCode,
                depot.DepotName,
                stock.DepotSectionsCode,
@@ -230,15 +231,25 @@
            
            rackingTaskDict.TryGetValue(barcodeToMatch, out var rackingTask);
            string stockStatus = "进入立库的路上";
            if (rackingTask?.Code != null)
            string stockStatus;
            if (rackingTask?.TaskType == "立库出库请求")
            {
                stockStatus = rackingTask.Code == "200" ? "已在立库中" : "进入立库的路上";
                // 出库请求:Code=200表示已出库,Code=null表示出库路上
                stockStatus = rackingTask.Code == "200" ? "已出立库" : "出立库路上";
            }
            else
            {
                // 回库请求(默认):Code=200表示已在立库中,Code=null表示进入立库的路上
                stockStatus = rackingTask?.Code == "200" ? "已在立库中" : "进入立库的路上";
            }
            // 冻结标识为1时,IqcStatus为0;否则根据IqcStatus判断
            var iqcStatusValue = x.Visible == 1 ? "0" :
                (x.IqcStatus == "特采直接使用" || x.IqcStatus == "已检" || x.IqcStatus == "免检" ? "1" : "0");
            return new
            {
                IqcStatus = x.IqcStatus == "已检" ? "1" : "0",
                IqcStatus = iqcStatusValue,
                ItemType = x.DepotName == "原材料仓" ? "0" : "1",
                StackCode = rackingTask?.PalletCode,
                x.DepotCode,
@@ -340,109 +351,13 @@
            }
        };
    }
    /// <summary>
    ///     查询可以退货的物料(旧版本,保留兼容)
    /// </summary>
    /// <returns>可退货物料库存列表</returns>
    public List<ReturnableStockDto> GetReturnableStocks()
    {
        // 优化点1: 使用原生SQL在数据库端完成去重和排序,避免全表加载到内存
        // Oracle 11g使用ROW_NUMBER()窗口函数获取每个条码的最新记录
        var rackingTaskSql = @"
            SELECT ITEM_BARCODE AS ItemBarcode, PALLETCODE AS PalletCode, CODE AS Code
            FROM (
                SELECT ITEM_BARCODE, PALLETCODE, CODE,
                       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 IS NULL OR CODE != '500')
            ) WHERE RN = 1";
        var rackingTaskData = Db.Ado.SqlQuery<RackingTaskDto>(rackingTaskSql);
        if (rackingTaskData == null || !rackingTaskData.Any())
        {
            return new List<ReturnableStockDto>();
        }
        // 优化点2: 过滤null值并使用字典提高条码匹配效率,从O(n)降低到O(1)
        var validRackingData = rackingTaskData.Where(x => !string.IsNullOrEmpty(x.ItemBarcode)).ToList();
        var rackingTaskDict = validRackingData.ToDictionary(x => x.ItemBarcode);
        var distinctBarcodes = validRackingData.Select(x => x.ItemBarcode).ToList();
        // 优化点3: 在数据库层面完成关联查询,一次性获取所有需要的数据
        var queryResult = 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) &&
                stock.Quantity > 0)
            .Select((stock, item, depot, org, unit) => new
            {
                stock.IqcStatus,
                stock.StackCode,
                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
            })
            .ToList();
        // 优化点4: 使用字典查找替代Where().FirstOrDefault(),提高匹配性能
        var result = queryResult.Select(x =>
        {
            rackingTaskDict.TryGetValue(x.ItemBarcode, out var rackingTask);
            string stockStatus = "0";
            if (rackingTask?.Code != null)
            {
                stockStatus = rackingTask.Code == "200" ? "1" : "2";
            }
            return new ReturnableStockDto
            {
                IqcStatus = x.IqcStatus == "已检" ? "1" : "0",
                ItemType = x.DepotName == "原材料仓" ? "0" : "1",
                StackCode = x.StackCode,
                DepotCode = x.DepotCode,
                DepotName = x.DepotName,
                DepotSectionsCode = x.DepotSectionsCode,
                ItemNo = x.ItemNo,
                ItemName = x.ItemName,
                ItemModel = x.ItemModel,
                Quantity = x.Quantity,
                ItemUnit = x.ItemUnit,
                ItemUnitName = x.ItemUnitName,
                IndepDate = x.IndepDate,
                OrgCode = x.OrgCode,
                OrgName = x.OrgName,
                ItemBarcode = x.ItemBarcode,
                StockStatus = stockStatus
            };
        }).ToList();
        return result;
    }
    private class RackingTaskDto
    {
        public string ItemBarcode { get; set; }
        public string PalletCode { get; set; }
        public string Code { get; set; }
        public string TaskType { get; set; }
    }
    /// <summary>
@@ -489,6 +404,20 @@
                    .Select(x => new { x.PalletCode, x.WidthType })
                    .First();
                // 检查是否存在未完成的任务(基于PalletCode,Code为null)
                if (!string.IsNullOrEmpty(rackingTaskInfo?.PalletCode))
                {
                    var pendingTask = Db.Queryable<XbRackingTaskSyxtLog>()
                        .Where(x => x.PalletCode == rackingTaskInfo.PalletCode && x.Code == null)
                        .OrderByDescending(x => x.Id)
                        .First();
                    if (pendingTask != null)
                    {
                        throw new Exception($"托盘编号 {rackingTaskInfo.PalletCode} 已存在未完成的立库任务,请等待任务完成后再操作。");
                    }
                }
                try
                {
                    // 1. 查询该条码对应的库存信息,按物料和批号汇总