杨前锦
2025-07-01 a93b0e99036c24b9bd58c79bf5e7364b1ba28bae
HH.WCS.Mobox3/HH.WCS.Mobox3.YNJT_PT/wms/WMSHelper.cs
@@ -507,15 +507,31 @@
        /// </summary>
        /// <param name="locNum"></param>
        /// <param name="itemCode"></param>
        /// <param name="roadway"></param>
        /// <param name="excludeRoadway"></param>
        /// <returns></returns>
        public static EndLocGroup getInStockEndLoc(int locNum, string itemCode)
        public static EndLocGroup getInStockEndLoc(int locNum, string itemCode , int roadway = 0 ,int excludeRoadway = 0)
        {
            var db = new SqlHelper<object>().GetInstance();
            EndLocGroup endLocGroup = new EndLocGroup { endLocList = new List<Location>() };
            // 1. 获取候选巷道列表(物料均衡或巷道均衡)
            var candidateRoadways = GetCandidateRoadways(db, itemCode);
            if (candidateRoadways.Count == 0) return endLocGroup;
            List<int> candidateRoadways = new List<int>();
            if (roadway == 0)
            {
                candidateRoadways = GetCandidateRoadways(db, itemCode);
                if (candidateRoadways.Count == 0) return endLocGroup;
                if (excludeRoadway != 0)
                {
                    candidateRoadways.Remove(excludeRoadway);
                }
            }
            else
            {
                candidateRoadways.Add(roadway);
            }
            // 2. 处理单货位入库
            if (locNum == 1)
@@ -532,38 +548,62 @@
        /// </summary>
        private static List<int> GetCandidateRoadways(SqlSugarClient db, string itemCode)
        {
            var list = new List<int>();
            // 策略1:巷道内同规格物料 < 10 的巷道(按数量升序)
            var materialRoadways = db.Queryable<Location>()
                .LeftJoin<LocCntrRel>((a, b) => a.S_CODE == b.S_LOC_CODE)
                .LeftJoin<CntrItemRel>((a, b, c) => b.S_CNTR_CODE == c.S_CNTR_CODE)
                .Where((a, b, c) =>
                    a.S_AREA_CODE == Settings.stockArea &&
                    a.N_CURRENT_NUM == 1 &&
                    a.N_LOCK_STATE == 0 &&
                    a.C_ENABLE == "Y" &&
                    b.S_CNTR_CODE != null &&
                    c.S_ITEM_CODE == itemCode)
                .GroupBy(a => a.N_ROADWAY)
                .Having(a => SqlFunc.AggregateCount(a.S_CODE) < 10)
                .Select(a => new { Roadway = a.N_ROADWAY, Count = SqlFunc.AggregateCount(a.S_CODE) })
                .OrderBy(a => a.Count)
                .Select(a => a.Roadway)
                .ToList();
            var materialRoadwayGroup = db.Queryable<Location>()
                        // 表别名:a = Location, b = LocCntrRel, c = CntrItemRel
                        .LeftJoin<LocCntrRel>((a, b) => a.S_CODE == b.S_LOC_CODE)
                        .LeftJoin<CntrItemRel>((a, b, c) => b.S_CNTR_CODE == c.S_CNTR_CODE)
            if (materialRoadways.Count > 0) return materialRoadways;
                        // 基础筛选条件(所有位置)
                        .Where((a, b, c) =>
                            a.S_AREA_CODE == Settings.stockArea &&  // 指定区域
                            a.N_LOCK_STATE == 0 &&                 // 未锁定
                            a.C_ENABLE == "Y")                     // 启用状态
            // 策略2:所有巷道按空货位数降序排序
            return db.Queryable<Location>()
                .Where(a =>
                    a.S_AREA_CODE == Settings.stockArea &&
                    a.N_CURRENT_NUM == 0 &&
                    a.N_LOCK_STATE == 0 &&
                    a.C_ENABLE == "Y")
                .GroupBy(a => a.N_ROADWAY)
                .Select(a => new { Roadway = a.N_ROADWAY, Count = SqlFunc.AggregateCount(a.S_CODE) })
                .OrderByDescending(a => a.Count)
                .Select(a => a.Roadway)
                .ToList();
                        // 按巷道分组(使用原始表字段)
                        .GroupBy((a, b, c) => a.N_ROADWAY)
                        // 选择分组结果(包含聚合计算)
                        .Select((a, b, c) => new
                        {
                            Roadway = a.N_ROADWAY,  // 巷道编号
                            // 统计满足特定条件的数量:
                            // 1. 当前数量=1 (a.N_CURRENT_NUM == 1)
                            // 2. 物料匹配 (c.S_ITEM_CODE == itemCode)
                            // 3. 容器关联存在 (b.S_CNTR_CODE != null)
                            validCount = SqlFunc.AggregateSum(SqlFunc.IIF(
                                a.N_CURRENT_NUM == 1 &&
                                c.S_ITEM_CODE == itemCode &&
                                b.S_CNTR_CODE != null,
                                1, 0))
                        })
                       .ToList();
            if (materialRoadwayGroup.Count > 0)
            {
                list = materialRoadwayGroup.Where(a => a.validCount < 10).OrderBy(a => a.validCount).Select(a => a.Roadway).ToList();
            }
            if (list.Count == 0)
            {
                // 策略2:所有巷道按空货位数降序排序
                materialRoadwayGroup = db.Queryable<Location>()
                    .Where(a =>
                        a.S_AREA_CODE == Settings.stockArea &&
                        a.N_CURRENT_NUM == 0 &&
                        a.N_LOCK_STATE == 0 &&
                        a.C_ENABLE == "Y")
                    .GroupBy(a => a.N_ROADWAY)
                    .Select(a => new { Roadway = a.N_ROADWAY, validCount = SqlFunc.AggregateCount(a.S_CODE) })
                    .ToList();
                list = materialRoadwayGroup.OrderByDescending(a => a.validCount).Select(a => a.Roadway).ToList();
            }
            return list;
        }
        /// <summary>
@@ -657,6 +697,7 @@
            // 按层->列排序,便于查找相邻
            var sorted = locations
                .OrderBy(l => l.N_LAYER)
                .ThenBy(l => l.N_ROW)
                .ThenBy(l => l.N_COL)
                .ToList();
@@ -733,6 +774,7 @@
            {
                query = query.Where((a, b, c) => c.S_ITEM_CODE == itemCode);
            }
            query = query.OrderByDescending((a, b, c) => a.N_ROADWAY == prevLoc.N_ROADWAY);
            var outLocList = query.ToList();
            if (outLocList.Count > 0)
@@ -740,13 +782,17 @@
                foreach (var loc in outLocList)
                {
                    // 查询巷道是否正常,异常跳过
                    var stackerStates = WCSDispatch.getStackerState(loc.N_ROADWAY);
                    if (stackerStates.Count == 0 || stackerStates[0].roadway_state == "0" || stackerStates[0].roadway_state == "3")
                    var deviceConfig = Settings.deviceConfigList.Where(a => a.roadway == loc.N_ROADWAY).First();
                    if (deviceConfig != null)
                    {
                        continue;
                        var stackerStates = WCSDispatch.getDeviceStatus(new List<string>() { deviceConfig.deviceNo } );
                        if ( stackerStates.Count == 0 || stackerStates[0].workStatus != 1 || stackerStates[0].manualStatus == 1 )
                        {
                            continue;
                        }
                    }
                    startLoc = loc;
                    break;
                }
            }
            return startLoc;
@@ -775,25 +821,32 @@
        /// 查询巷道任务最少的接驳位
        /// </summary>
        /// <returns></returns>
        public static Location getMinTaskMiddleLoc(int type)
        public static Location getMinTaskMiddleLoc(int type , int roadway = 0 , int excludeRoadway = 0)
        {
            Location location = new Location();
            var db = new SqlHelper<object>().GetInstance();
            var roadwayGroup = db.Queryable<Location>()
            var query = db.Queryable<Location>()
                    .LeftJoin<WCSTask>((a, b) => a.S_CODE == b.S_END_LOC && b.N_B_STATE < 3)
                    .Where((a, b) => a.S_AREA_CODE == Settings.stockArea)
                    .GroupBy((a, b) => a.N_ROADWAY)
                    .Where((a, b) => a.S_AREA_CODE == Settings.stockArea);
            if (roadway != 0)
            {
                query = query.Where((a, b) => a.N_ROADWAY == roadway);
            }
            if (excludeRoadway != 0)
            {
                query = query.Where((a, b) => a.N_ROADWAY != excludeRoadway);
            }
            var roadwayGroup = query.GroupBy((a, b) => a.N_ROADWAY)
                    .Select((a, b) => new { roadway = a.N_ROADWAY, num = SqlFunc.AggregateDistinctCount(b.S_CODE != null) })
                    .OrderBy(a => a.num)
                    .ToList();
            foreach (var item in roadwayGroup)
            {
                // 1.查询巷道内的堆垛机状态是否正常
                // 2.查询接驳位
                var connectLoc = Settings.connectLocList.Where(a => a.type == type && a.roadway == item.roadway).FirstOrDefault();
                var connectLoc = Settings.connectLocList.Where(a => a.roadway == item.roadway).FirstOrDefault();
                if (connectLoc != null) 
                {
                    location = LocationHelper.GetLoc(connectLoc.locCode);
@@ -804,6 +857,38 @@
        }
        /// <summary>
        /// 查询上线货位
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Location getOnlneLoc(int type)
        {
            Location location = null;
            var connectLoc = Settings.onLineLocList.Where(a => a.type == type).FirstOrDefault();
            if (connectLoc != null)
            {
                location = LocationHelper.GetLoc(connectLoc.locCode);
            }
            return location;
        }
        /// <summary>
        /// 查询叫料异常排出位
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        public static Location getCallOutLoc(int row)
        {
            Location location = null;
            var connectLoc = Settings.callOutLocList.Where(a => a.row == row).FirstOrDefault();
            if (connectLoc != null)
            {
                location = LocationHelper.GetLoc(connectLoc.locCode);
            }
            return location;
        }
        /// <summary>
        /// 查询物料存放时间配置信息
        /// </summary>
        /// <param name="bc_entried"></param>