| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 | using SqlSugar;using System;using System.Collections.Generic;using System.Data;using System.Globalization;using System.Linq;using wms.dto.response.sx;using wms.sqlsugar;using wms.sqlsugar.model.sx;namespace wms.service.Extensions{    /// <summary>    /// 时效服务扩展    /// </summary>    public static class SxServiceExtension    {        #region 焊点计算        /// <summary>        /// 装箱时处理焊点盘        /// </summary>        /// <param name="rule">箱号对应的装箱规则</param>        /// <param name="invlist">库存信息</param>        /// <param name="outInvlist">后续可用的不带焊点盘信息</param>        /// <returns>填充后的焊点盘列表</returns>        public static List<StockTemp> ProcessWeldingPointsBoxing(BillPboxrule rule, IEnumerable<StockTemp>? invlist, out IEnumerable<StockTemp>? outInvlist)        {            var solderinvlist = new List<StockTemp>();            invlist ??= Enumerable.Empty<StockTemp>();            // 如果不控制焊点盘数,则直接按生产时间排序后返回            if (rule.SolderMaxCount <= 0)            {                outInvlist = invlist.OrderBy(p => p.ProductTime);                return solderinvlist;            }            // 计算需要获取的焊点盘数量            int itemsPerBox = (rule.SpoolType == "BS60" || rule.SpoolType == "BS40") ? 72 : 36;            int requiredSolderBoxes = Math.Max(0, rule.FullCountQty / itemsPerBox * rule.SolderMaxCount);            // 获取所有带焊点的盘并排序            var availableSolders = invlist.Where(p => p.SolderCount > 0).OrderBy(p => p.ProductTime).ThenByDescending(p => p.SolderCount).ToList();            // 根据是否管控总焊点数量来选择不同的策略            if (rule.PerSolderMaxCount <= 0)            {                // 不管控总焊点数量,直接取前 N 个                solderinvlist = availableSolders.Take(requiredSolderBoxes).ToList();            }            else            {                // 管控总焊点数量,使用 GetWeldingPointsBoxing 方法                solderinvlist = GetWeldingPointsBoxing(                    currentBoxes: solderinvlist,                    maxBoxCount: requiredSolderBoxes,                    maxTotalSolderCount: rule.PerSolderMaxCount,                    inventory: availableSolders                );            }            // 剩余可用库存为无焊点的            outInvlist = invlist.Where(p => p.SolderCount == 0);            return solderinvlist;        }        /// <summary>        /// 获取焊点盘(装箱处理)        /// </summary>        /// <param name="currentBoxes">已有的焊点盘</param>        /// <param name="maxBoxCount">最大焊点盘数</param>        /// <param name="maxTotalSolderCount">最大焊点总数</param>        /// <param name="inventory">库存信息</param>        /// <returns>填充后的焊点盘列表</returns>        public static List<StockTemp> GetWeldingPointsBoxing(List<StockTemp> currentBoxes, int maxBoxCount, int maxTotalSolderCount, IEnumerable<StockTemp>? inventory)        {            if (inventory == null || !inventory.Any()) return currentBoxes;            // 当前状态统计            var currentBoxCount = currentBoxes.Count;            var currentTotalSolderCount = currentBoxes.Sum(x => x.SolderCount);            // 如果已经满载,直接返回            if (currentBoxCount >= maxBoxCount || currentTotalSolderCount >= maxTotalSolderCount) return currentBoxes;            // 将库存转换为列表并排序,避免重复排序            var availableInventory = inventory.Where(p => p.SolderCount > 0).OrderBy(p => p.ProductTime).ThenByDescending(p => p.SolderCount).ToList();            foreach (var item in availableInventory)            {                // 判断是否还能继续添加                if (currentBoxCount >= maxBoxCount || currentTotalSolderCount >= maxTotalSolderCount) break;                // 添加当前项                currentBoxes.Add(item);                currentBoxCount++;                currentTotalSolderCount += item.SolderCount;            }            return currentBoxes;        }        #endregion 焊点计算        #region 获取码垛位        /// <summary>        /// 根据配置信息获取可用码垛位        /// </summary>        /// <param name="palletizingList">现有码垛位</param>        /// <param name="config">配置表</param>        /// <param name="code">配置信息code</param>        /// <returns></returns>        public static List<sxSysConfig> GetAvailablePalletizingStationsByConfiguration(this List<sxSysConfig> palletizingList, Repository<sxSysConfig> config, string code)        {            // 获取配置中的机器人列表            var configuredRobots = config.GetFirst(x => x.Code == code).SContent.Split("|").Select(x => ToTitleCase(x));            // 定义机器人及其对应的码垛位映射关系            var robotToPalletizingMap = new Dictionary<string, List<string>>            {               { "Robot1", new List<string> { "8090", "8092" } },               { "Robot2", new List<string> { "8096", "8098" } },               { "Robot3", new List<string> { "8307" } }            };            // 获取所有符合条件的码垛位            var availablePalletizingCodes = configuredRobots                .SelectMany(robot =>                {                    if (robotToPalletizingMap.TryGetValue(robot, out var palletizing))                    {                        return palletizing;                    }                    return Enumerable.Empty<string>();                })                .Distinct();            // 返回匹配的码垛位列表            return palletizingList.Where(palletizing => availablePalletizingCodes.Contains(palletizing.Code)).ToList();        }        /// <summary>        /// 根据配置信息获取可用机械臂        /// </summary>        /// <param name="palletizingList">现有码垛位</param>        /// <param name="config">配置表</param>        /// <param name="code">配置信息code</param>        /// <returns></returns>        public static List<string> GetAvailablePalletizingRobotsByConfiguration(this List<string> palletizingList, Repository<sxSysConfig> config, string code)        {            // 获取配置中的机器人列表            var configuredRobots = config.GetFirst(x => x.Code == code).SContent.Split("|").Select(x => ToTitleCase(x));            // 返回匹配的码垛位列表            return palletizingList.Select(x => ToTitleCase(x)).Where(x => configuredRobots.Contains(x)).ToList();        }        /// <summary>        /// 将字符串转换为首字母大写,其他全小写        /// </summary>        /// <param name="str"></param>        /// <returns></returns>        public static string ToTitleCase(string str)        {            if (string.IsNullOrEmpty(str))            {                return str;            }            // 将字符串转换为全小写            string lowerStr = str.ToLower();            // 使用 TextInfo.ToTitleCase 转换为标题大小写            TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;            string titleCasedStr = textInfo.ToTitleCase(lowerStr);            return titleCasedStr;        }        #endregion 获取码垛位    }}
 |