杨前锦
2025-06-19 d42ad8b01195def2a9309930e14f90ff13ad47b1
HH.WCS.Mobox3/HH.WCS.Mobox3.FJJT/wms/TEST.cs
New file
@@ -0,0 +1,237 @@
using HH.WCS.Mobox3.FJJT.util;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
namespace HH.WCS.Mobox3.FJJT.wms
{
    /// <summary>
    /// 密集型库区
    /// </summary>
    internal class TEST
    {
        static TEST() {
            //InitRowLockTable(new List<string> { "PGKQ", "PGKTK" });
        }
        /// <summary>
        /// 根据库区和物料获取入库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在)
        /// </summary>
        /// <param name="area"></param>
        /// <param name="itemCode">如果itemCode是空表示空容器</param>
        /// <param name="standardCarryQty">标准搬运数量</param>
        /// <returns></returns>
        public static Location GetTN_Location4In(string area, string itemCode, string itemBatch, int standardCarryQty = 1) {
            Location result = null;
            try {
                //1.0 获取每一排最大的列
                //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除
                var listMaxCol = new SqlHelper<Location>().GetInstance().Queryable<Location>().Where(a => a.S_AREA_CODE == area).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
                //1.1 查到所有有容器的排
                var db = new SqlHelper<object>().GetInstance();
                var list = db.Queryable<Location>().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area).Includes(a => a.LocCntrRel, a => a.CntrItemRels).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
                if (list.Count > 0) {
                    for (int i = list.Count - 1; i >= 0; i--) {
                        //排除已经锁定的货位 和 放满了且是最大列的货位
                        //其它项目还需要查询排锁
                        if (list[i].N_LOCK_STATE== 0 || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_CODE == list[i].S_CODE) > 0)) {
                            list.Remove(list[i]);
                        }
                    }
                    if (list.Count > 0) {
                        //1.21 加载货位的容器信息 (mapper之前只能是查询原始数据,如果有其他查询 mapper失效)
                        #region MyRegion
                        /*
                        Console.WriteLine("加载货位的容器信息");
                        db.ThenMapper(list, loc => {
                            loc.LocCntrRel = db.Queryable<LocCntrRel>().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault();
                        });
                        //1.22 加载容器的物料信息
                        Console.WriteLine("加载容器的物料信息");
                        db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => {
                            lcr.CntrItemRel = db.Queryable<CntrItemRel>().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault();
                        });
                      */
                        #endregion
                        //1.3 遍历判断物料类型是否相同
                        for (int i = 0; i < list.Count; i++) {
                            //todo 还需要判断锁
                            #region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空
                            if (list[i].LocCntrRel != null) {
                                //LogHelper.Info("itemCode=" + itemCode);
                                if ((itemCode != null && list[i].LocCntrRel.CntrItemRels != null && list[i].LocCntrRel.CntrItemRels[0].S_ITEM_CODE.Trim() == itemCode && list[i].LocCntrRel.CntrItemRels[0].S_BATCH_NO.Trim() == itemBatch.Trim()) || (itemCode == null && list[i].LocCntrRel.CntrItemRels == null)) {
                                    if (list[i].N_CURRENT_NUM < list[i].N_CAPACITY) {
                                        //1.31 如果搬运数量=1
                                        //1.32 搬运多个容器,例如3+3模式 ,必须当前数量=0或3;如果是3+3+,必须当前数量=0或3或6
                                        if (list[i].N_CURRENT_NUM % standardCarryQty == 0) {
                                            result = list[i];
                                        }
                                        else {
                                            //1.33 不满足则选择后一列,后一列肯定是空货位
                                            result = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).OrderBy(a => a.N_COL).First();
                                        }
                                    }
                                    else {
                                        //当前货位满了,比他col大一位的货位,后一列肯定是空货位
                                        result = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).OrderBy(a => a.N_COL).First();
                                    }
                                    if (result != null) {
                                        break;
                                    }
                                }
                            }
                            else {
                                LogHelper.Info("货位容器物料信息为空");
                            }
                            #endregion
                        }
                    }
                }
                if (result == null) {
                    //todo 还需要判断锁
                    #region 查找所有数量是空的排
                    //2.0 简化查询只查每一排第一列
                    list = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area).OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList();
                    //2.1 选一个空排
                    for (int i = 0; i < list.Count; i++) {
                        if (list[i].N_LOCK_STATE== 0) {
                            //二次校验当前排所有货位都是空的,防止系统数据错乱
                            var rowSumInfo = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW).Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First();
                            if (rowSumInfo.sum == 0) {
                                result = list[i];
                                break;
                            }
                        }
                    }
                    #endregion
                }
            }
            catch (Exception ex) {
                Console.WriteLine("GetTN_Location4In:" + ex.Message + ex.StackTrace);
                LogHelper.Error("GetTN_Location4In:" + ex.Message, ex);
            }
            return result;
        }
        /// <summary>
        /// 根据库区和物料获取出库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在)
        /// </summary>
        /// <param name="area"></param>
        /// <param name="itemCode">如果itemCode是空表示空容器</param>
        /// <param name="standardCarryQty">标准搬运数量</param>
        /// <returns></returns>
        /// <returns></returns>
        public static Location GetTN_Location4Out(string area, string itemCode, string itemBatch, int standardCarryQty = 1) {
            Console.WriteLine($"area={area}");
            Location result = null;
            var db = new SqlHelper<Location>().GetInstance();
            //1.0 查到所有有容器的排 var list = db.Queryable<TN_Location>().Where(a => a.N_CURRENT_NUM>0).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList();
            var list = db.Queryable<Location>().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area).Includes(a => a.LocCntrRel, a => a.CntrItemRels).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList();
            //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除
            if (list.Count > 0) {
                //LogHelper.Info("GetTN_Location4Out:" + JsonConvert.SerializeObject(list));
                #region MyRegion
                /*
                      //1.21 加载货位的容器信息
                      db.ThenMapper(list, loc => {
                          loc.LocCntrRel = db.Queryable<LocCntrRel>().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault();
                      });
                      //1.22 加载容器的物料信息
                      db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => {
                          lcr.CntrItemRel = db.Queryable<CntrItemRel>().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault();
                      });
                      */
                #endregion
                //1.3 遍历判断物料类型是否相同
                for (int i = 0; i < list.Count; i++) {
                    //todo 还需要判断锁
                    #region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空
                    if (list[i].N_LOCK_STATE== 0 && list[i].LocCntrRel != null) {
                        if ((itemCode != null && list[i].LocCntrRel.CntrItemRels != null && list[i].LocCntrRel.CntrItemRels[0].S_ITEM_CODE.Trim() == itemCode && (itemBatch == null || list[i].LocCntrRel.CntrItemRels[0].S_BATCH_NO.Trim() == itemBatch.Trim())) || (itemCode == null && list[i].LocCntrRel.CntrItemRels == null)) {
                            //搬运选择货位
                            //如果当前出库位后面有空位,不能是入库中
                            var after = new SqlHelper<Location>().Get(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL == list[i].N_COL + 1);
                            if (after == null || after.N_LOCK_STATE== 0) {
                                result = list[i];
                            }
                            if (result != null) {
                                break;
                            }
                        }
                    }
                    #endregion
                }
            }
            return result;
        }
        private static List<int> GetRowsByArea(string area) {
            var list = new SqlHelper<Location>().GetInstance().Queryable<Location>().Where(a => a.S_AREA_CODE == area).Distinct().Select(a => a.N_ROW).ToList();
            return list;
        }
        internal static void Test() {
            //UnLockLoc("PGKQ-02-02");
            //LockLoc("PGKQ-02-02", "入库锁");
            //Binding("PGKQ-02-03", "AAA", "", 3);
            //UnBinding("PGKQ-02-03", 2);
            //var full = GetTN_Location4In("PGKQ", "AAA");
            //var empty = GetTN_Location4In("PGKQ", null);
            //var fullOut = GetTN_Location4Out("PGKQ", "AAA");
            //var emptyOut = GetTN_Location4Out("PGKQ", null);
            //var TN_Locations = new SqlHelper<TN_Location>().GetList();
            //var LocCntrRels = new SqlHelper<LocCntrRel>().GetList();
            //var CntrItemRels = new SqlHelper<CntrItemRel>().GetList();
            //var list = new SqlHelper<TN_Location>().GetInstance().Queryable<TN_Location>().LeftJoin<LocCntrRel>((l, lc) => l.S_LOC_CODE == lc.S_LOC_CODE).ToList();
            //var results = context.Client.Queryable<Employee>().Mapper(t=>t.Person, p=>p.PersonId).ToList();
            var db = new SqlHelper<object>().GetInstance();
            //var list = db.Queryable<TN_Location>().Mapper(l => l.LocCntrRel, lcr => lcr.S_LOC_CODE).Where(a=>a.S_LOC_CODE== "PGKQ-01-01").ToList();
            //多级查询会嵌套,需要指定导航属性和主键,循环嵌套查询不建议
            //[Navigate(NavigateType.OneToOne, nameof(S_LOC_CODE))]、 [Navigate(NavigateType.OneToOne, nameof(S_CNTR_CODE))]、[SugarColumn(IsPrimaryKey = true)]
            var list = db.Queryable<Location>().Where(a => a.N_CURRENT_NUM > 0).Includes(a => a.LocCntrRel, a => a.CntrItemRels).ToList();
            #region MyRegion
            /*
            // SetContext不会生成循环操作,高性能  和直接Where性能是不一样的
            var list = db.Queryable<TN_Location>().Where(a => a.N_CURRENT_NUM > 0).ToList();
            //第一层
            db.ThenMapper(list, loc => {
                loc.LocCntrRel = db.Queryable<LocCntrRel>().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault();
            });
            //第二层
            db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => {
                lcr.CntrItemRel = db.Queryable<CntrItemRel>().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault();
            });
            */
            #endregion
        }
    }
}