Exemple #1
0
        /// <summary>
        /// 在指定的巷道和分组中分配一个货位以供入库。
        /// </summary>
        /// <param name="laneway">要在其中分配货位的巷道。</param>
        /// <param name="excludedIdList">要排除的货位。</param>
        /// <param name="excludedColumnList">要排除的列。</param>
        /// <param name="excludedLevelList">要排除的层。</param>
        /// <param name="cargoInfo">入库的货物信息。</param>
        /// <param name="orderBy">排序依据。这是 LocationUnit 类的属性名。</param>
        /// <returns>
        /// 从不返回 null。
        /// </returns>
        public async Task <SResult> AllocateAsync(
            Laneway laneway,
            UnitloadStorageInfo cargoInfo,
            int[] excludedIdList     = null,
            int[] excludedColumnList = null,
            int[] excludedLevelList  = null,
            string orderBy           = "i1")
        {
            if (laneway == null)
            {
                throw new ArgumentNullException(nameof(laneway));
            }

            if (string.IsNullOrWhiteSpace(orderBy))
            {
                throw new ArgumentException("参数 orderBy 不能为 null 或空字符串。");
            }

            _logger.Debug("巷道 {lanewayCode}", laneway.LanewayCode);

            var       rules = _rules.Where(x => x.DoubleDeep == laneway.DoubleDeep).OrderBy(x => x.Order);
            Stopwatch sw    = new Stopwatch();

            foreach (var rule in rules)
            {
                _logger.Debug("正在测试 {ruleName}", rule.Name);
                sw.Restart();
                var loc = await rule.SelectAsync(laneway, cargoInfo, excludedIdList, excludedColumnList, excludedLevelList, orderBy).ConfigureAwait(false);

                sw.Stop();

                //// TODO 涉及巷道过多时,会打开很多session,需优化
                //ThreadPool.QueueUserWorkItem(state =>
                //{
                //    using (ILifetimeScope scope = _lifetimeScope.BeginLifetimeScope())
                //    {
                //        var ruleNames = _rules.Select(x => x.Name);
                //        RuleStatHelper ruleStatHelper = scope.Resolve<RuleStatHelper>(TypedParameter.From(ruleNames));
                //        ruleStatHelper.Update(rule.Name, loc, DateTime.Now, sw.ElapsedMilliseconds);
                //    }
                //});
                if (loc != null)
                {
                    _logger.Debug("{ruleName} 成功分配到货位 {locationCode}", rule.Name, loc.LocationCode);
                    return(SResult.MakeSuccess(loc));
                }
                else
                {
                    _logger.Debug("{ruleName} 失败", rule.Name);
                }
            }

            return(SResult.Failure);
        }
Exemple #2
0
        /// <summary>
        /// 在指定的巷道和分组中分配一个货位以供入库。
        /// </summary>
        /// <param name="laneway">要在其中分配货位的巷道。</param>
        /// <param name="excludedIdList">要排除的货位。</param>
        /// <param name="excludedColumnList">要排除的列。</param>
        /// <param name="excludedLevelList">要排除的层。</param>
        /// <param name="storageInfo">入库货物信息。</param>
        /// <param name="orderBy">排序依据。这是 LocationUnit 类的属性名。</param>
        /// <returns></returns>
        public async Task <Location> SelectAsync(Laneway laneway, UnitloadStorageInfo storageInfo, int[] excludedIdList, int[] excludedColumnList, int[] excludedLevelList, string orderBy)
        {
            if (laneway == null)
            {
                throw new ArgumentNullException("laneway");
            }

            if (storageInfo == null)
            {
                throw new ArgumentNullException("cargoInfo");
            }

            if (string.IsNullOrWhiteSpace(orderBy))
            {
                throw new ArgumentException("参数 orderBy 不能为 null 或空字符串。");
            }

            if (laneway.DoubleDeep != this.DoubleDeep)
            {
                string msg = $"巷道类型不匹配,此规则适用于单深巷道,但传入的巷道是双深。【{laneway.LanewayCode}】。";
                throw new InvalidOperationException(msg);
            }

            if (laneway.Offline)
            {
                _logger.Warning("巷道 {lanewayCode} 已离线", laneway.LanewayCode);
                return(null);
            }

            string queryString = $@"
SELECT loc.LocationId
FROM Location loc
JOIN loc.Rack rack
JOIN loc.Cell c
WHERE rack.Laneway = :laneway

AND loc.Exists = true
AND loc.UnitloadCount = 0
AND loc.OutboundCount = 0
AND loc.InboundDisabled = false
AND loc.InboundCount = 0
AND loc.WeightLimit >= :weight
AND loc.HeightLimit >= :height
AND loc.StorageGroup = :storageGroup
AND loc.Specification = :locSpec
{"AND loc.LocationId NOT IN (:excludedIdList)".If(excludedIdList)}
{"AND loc.Column NOT IN (:excludedColumnList)".If(excludedColumnList)}
{"AND loc.Level NOT IN (:excludedLevelList)".If(excludedLevelList)}

ORDER BY loc.WeightLimit, loc.HeightLimit, c.$orderBy 
";

            queryString = queryString.Replace("$orderBy", orderBy);

            IQuery q = _session
                       .CreateQuery(queryString)
                       .SetParameter("laneway", laneway)
                       .SetParameter("weight", storageInfo.Weight)
                       .SetParameter("height", storageInfo.Height)
                       .SetParameter("storageGroup", storageInfo.StorageGroup)
                       .SetParameter("locSpec", storageInfo.ContainerSpecification)
                       .EmptySafeSetParameterList("excludedIdList", excludedIdList)
                       .EmptySafeSetParameterList("excludedColumnList", excludedColumnList)
                       .EmptySafeSetParameterList("excludedLevelList", excludedLevelList)
                       .SetMaxResults(1);

            int?id = await q.UniqueResultAsync <int?>().ConfigureAwait(false);

            if (id == null)
            {
                return(null);
            }
            else
            {
                var loc = await _session.GetAsync <Location>(id.Value).ConfigureAwait(false);

                return(loc);
            }
        }
Exemple #3
0
        /// <summary>
        /// 在指定的巷道和分组中分配一个货位以供入库。
        /// </summary>
        /// <param name="laneway">要在其中分配货位的巷道。</param>
        /// <param name="excludedIdList">要排除的货位。</param>
        /// <param name="excludedColumnList">要排除的列。</param>
        /// <param name="excludedLevelList">要排除的层。</param>
        /// <param name="storageInfo">入库货物信息。</param>
        /// <param name="orderBy">排序依据。这是 LocationUnit 类的属性名。</param>
        /// <returns></returns>
        public async Task <Location> SelectAsync(Laneway laneway, UnitloadStorageInfo storageInfo, int[] excludedIdList, int[] excludedColumnList, int[] excludedLevelList, string orderBy)
        {
            if (laneway == null)
            {
                throw new ArgumentNullException(nameof(laneway));
            }

            if (storageInfo == null)
            {
                throw new ArgumentNullException("cargoInfo");
            }

            if (string.IsNullOrWhiteSpace(orderBy))
            {
                throw new ArgumentException("参数 orderBy 不能为 null 或空字符串。");
            }

            if (laneway.DoubleDeep != this.DoubleDeep)
            {
                string msg = $"巷道类型不匹配,此规则适用于双深巷道,但传入的巷道是单深。【{laneway.LanewayCode}】。";
                throw new InvalidOperationException(msg);
            }

            if (laneway.Offline)
            {
                _logger.Warning("巷道 {lanewayCode} 已离线", laneway.LanewayCode);
                return(null);
            }

            // 此规则向双深单元的一深分配
            // 使双深单元的有货标记从 01| 变为 11|
            // 会考虑二深的出库标记和分配标记
            string queryString = $@"
SELECT loc1.LocationId

FROM Location loc1
     JOIN loc1.Rack rack1
     JOIN loc1.Cell c,

     Location loc2
     JOIN loc2.Rack rack2


WHERE rack1.Deep = 1
AND rack2.Deep = 2 
AND loc1.Cell = loc2.Cell
AND rack1.Laneway = :laneway

AND loc2.Exists = true
AND loc2.UnitloadCount > 0
AND loc2.OutboundCount = 0
AND loc2.InboundCount = 0
AND NOT EXISTS (
    FROM Unitload 
    WHERE CurrentLocation = loc2 
    AND (OutFlag <> :outFlag OR Allocated = true)
)
AND loc1.Exists = true
AND loc1.UnitloadCount = 0
AND loc1.OutboundCount = 0
AND loc1.InboundDisabled = false
AND loc1.InboundCount = 0
AND loc1.WeightLimit >= :weight
AND loc1.HeightLimit >= :height
AND loc1.StorageGroup = :storageGroup
AND loc1.Specification = :locSpec
{"AND loc1.LocationId NOT IN (:excludedIdList)".If(excludedIdList)}
{"AND loc1.Column NOT IN (:excludedColumnList)".If(excludedColumnList)}
{"AND loc1.Level NOT IN (:excludedLevelList)".If(excludedLevelList)}

ORDER BY loc1.WeightLimit, loc1.HeightLimit, c.$orderBy
";

            queryString = queryString.Replace("$orderBy", orderBy);

            IQuery q = _session
                       .CreateQuery(queryString)
                       .SetParameter("laneway", laneway)
                       .SetParameter("outFlag", storageInfo.OutFlag)
                       .SetParameter("weight", storageInfo.Weight)
                       .SetParameter("height", storageInfo.Height)
                       .SetParameter("storageGroup", storageInfo.StorageGroup)
                       .SetParameter("locSpec", storageInfo.ContainerSpecification)
                       .EmptySafeSetParameterList("excludedIdList", excludedIdList)
                       .EmptySafeSetParameterList("excludedColumnList", excludedColumnList)
                       .EmptySafeSetParameterList("excludedLevelList", excludedLevelList)
                       .SetMaxResults(1);

            int?id = await q.UniqueResultAsync <int?>().ConfigureAwait(false);

            if (id == null)
            {
                return(null);
            }
            else
            {
                var loc = await _session.GetAsync <Location>(id.Value).ConfigureAwait(false);

                return(loc);
            }
        }