pengmn
2025-05-30 cd40ada4efe0d0a4036714cf597ce170b8cf5a54
HH.WCS.Mobox3.HangYang/process/TaskProcess.cs
@@ -12,6 +12,7 @@
using Swashbuckle.Swagger;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
@@ -1880,123 +1881,210 @@
        /// <summary>
        /// 根据配盘单生成出库任务
        /// </summary>
        /// <param name="distributionCntr">配盘单</param>
        /// <param name="distributionCntrs">配盘单</param>
        /// <returns></returns>
        internal static bool GenerateFromPicking(List<DistributionCntr> distributionCntr)
        internal static bool GenerateFromPicking(List<DistributionCntr> distributionCntrs)
        {
            try
            {
                // 创建调度器
                var scheduler = new DoubleDeepOutboundScheduler(distributionCntr);
                // 1. 初始化调度器和出库任务列表
                var scheduler = new DoubleDeepOutboundScheduler(distributionCntrs);
                var outboundTasks = CreateOutboundTasks(distributionCntrs);
                var listOut = new List<Outbound>();
                foreach (var item in distributionCntr)
                {
                    listOut.Add(new Outbound
                    {
                        locCode = item.S_LOC_CODE,
                        areaCode = item.S_AREA_CODE,
                        endArea = item.S_EXIT_AREA_CODE,
                        endBit = item.S_EXIT_LOC_CODE,
                        trayCode = item.S_CNTR_CODE,
                        taskType = "配盘出库"
                    });
                }
                // 请求出库
                var tasks = scheduler.GenerateOutboundTasks(listOut);
                // 2. 计算货位生成任务数据
                var tasks = scheduler.GenerateOutboundTasks(outboundTasks);
                if (!tasks.Any()) return false;
                foreach (var item in tasks)
                {
                    var wmsTask = new WMSTask();
                    if (string.IsNullOrEmpty(item.S_OP_CODE))
                    {
                        wmsTask = new WMSTask
                        {
                            S_CNTR_CODE = item.S_CNTR_CODE,
                            S_CODE = WMSHelper.GenerateTaskNo(),
                            S_START_LOC = item.S_START_LOC,
                            S_START_AREA = item.S_START_AREA,
                            S_END_LOC = item.S_END_LOC,
                            S_END_AREA = item.S_END_AREA,
                            S_START_WH = "CK001",
                            S_END_WH = "CK001",
                            N_B_STATE = 1,
                            S_B_STATE = "执行",
                            N_TYPE = 2,
                            S_TYPE = "配盘出库"
                        };
                        if (!WMSHelper.CreateWmsTask(wmsTask))
                        {
                            return false;
                        }
                    }
                // 3. 创建WMS作业
                var mainTask = CreateMainWmsTask(tasks.Where(s=>s.S_TYPE == "配盘出库").First());
                if (!WMSHelper.CreateWmsTask(mainTask)) return false;
                    if (item.S_END_AREA == "LXLKQ")
                    {
                        // 创建出库任务
                        var res = TaskProcess.HYCreateTransport(item.S_START_LOC, item.S_END_LOC, item.S_TYPE, item.S_CNTR_CODE, wmsTask.S_CODE);
                        UpdateDistributionCntrState(1, 2, item.S_CNTR_CODE);
                        if (!res)
                        {
                            LogHelper.Info($"根据配盘单生成出库任务创建出库任务失败!!");
                            return false;
                        }
                    }
                    else
                    {
                        //根据分拣货位去查询配置,如果分拣区没有空货位就去出库分拣暂存区
                        var relevancys = Settings.OutRelevancys.Where(s => s.conLoc == item.S_END_LOC).FirstOrDefault();
                        if (relevancys == null)
                        {
                            LogHelper.Info($"Settings未查询到集货位{item.S_END_LOC}对应的分拣位!", "杭氧");
                            break;
                        }
                        var locList = LocationHelper.GetLocListEmptyFree(relevancys.sorLoc.ToList());
                        if (locList.Any())
                        {
                            // 创建出库任务
                            var res = TaskProcess.HYCreateTransport(item.S_START_LOC, locList.FirstOrDefault().S_CODE, item.S_TYPE, item.S_CNTR_CODE, wmsTask.S_CODE);
                            UpdateDistributionCntrState(1, 2, item.S_CNTR_CODE);
                            if (!res)
                            {
                                LogHelper.Info($"根据配盘单生成出库任务创建出库任务失败!!");
                                return false;
                            }
                        }
                        else
                        {
                            var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "拣选缓存区").FirstOrDefault();
                            var lxLocations = LocationHelper.GetLocAreaList(reservoirs.areaCode);
                            if (lxLocations.Any())
                            {
                                // 创建出库任务
                                var res = TaskProcess.HYCreateTransport(item.S_START_LOC, lxLocations.FirstOrDefault().S_CODE, "配盘缓存", item.S_CNTR_CODE, wmsTask.S_CODE);
                                UpdateDistributionCntrState(1, 2, item.S_CNTR_CODE);
                                if (!res)
                                {
                                    LogHelper.Info($"根据配盘单生成出库任务创建出库任务失败!!");
                                    return false;
                                }
                            }
                        }
                    }
                }
                return true;
                // 4. 生成WMS主任务
                return ProcessAllTransportTasks(tasks, mainTask.S_CODE);
            }
            catch (Exception ex)
            {
                var st = new System.Diagnostics.StackTrace(ex, true);
                var frame = st.GetFrame(0); // 获取第一个堆栈帧
                if (frame != null)
                LogErrorWithStackTrace("根据配盘单生成出库任务失败", ex);
                return false;
            }
        }
        // --------------------- 辅助方法 ---------------------
        private static List<Outbound> CreateOutboundTasks(List<DistributionCntr> distributionCntrs)
        {
            return distributionCntrs.Select(item => new Outbound
            {
                locCode = item.S_LOC_CODE,
                areaCode = item.S_AREA_CODE,
                endArea = item.S_EXIT_AREA_CODE,
                endBit = item.S_EXIT_LOC_CODE,
                trayCode = item.S_CNTR_CODE,
                taskType = "配盘出库"
            }).ToList();
        }
        private static WMSTask CreateMainWmsTask(WCSTask firstTask)
        {
            return new WMSTask
            {
                S_CNTR_CODE = firstTask.S_CNTR_CODE,
                S_CODE = WMSHelper.GenerateTaskNo(),
                S_START_LOC = firstTask.S_START_LOC,
                S_START_AREA = firstTask.S_START_AREA,
                S_END_LOC = firstTask.S_END_LOC,
                S_END_AREA = firstTask.S_END_AREA,
                S_START_WH = "CK001",
                S_END_WH = "CK001",
                N_B_STATE = 1,
                S_B_STATE = "执行",
                N_TYPE = 2,
                S_TYPE = "配盘出库"
            };
        }
        private static bool ProcessAllTransportTasks(List<WCSTask> tasks, string wmsTaskCode)
        {
            foreach (var task in tasks.OrderBy(t => t.N_PRIORITY))
            {
                if (IsLxLkqOrRelocationTask(task))
                {
                    LogHelper.Error($"根据配盘单生成出库任务失败{ex.Message}!!", ex);
                    LogHelper.Error($"文件名: {frame.GetFileName()}", ex);
                    LogHelper.Error($"行号: {frame.GetFileLineNumber()}", ex);
                    LogHelper.Error($"列号: {frame.GetFileColumnNumber()}", ex);
                    if (!ProcessLxLkqTransportTask(task, wmsTaskCode))
                        return false;
                }
                else
                {
                    if (!ProcessNormalTransportTask(task, wmsTaskCode))
                        return false;
                }
            }
            return true;
        }
        private static bool IsLxLkqOrRelocationTask(WCSTask task)
        {
            return task.S_START_AREA == "LXLKQ" || task.S_TYPE == "深位移库";
        }
        /// <summary>
        /// 生成LXLKQ || 深位移库的配盘任务
        /// </summary>
        /// <param name="task"></param>
        /// <param name="wmsTaskCode"></param>
        /// <returns></returns>
        private static bool ProcessLxLkqTransportTask(WCSTask task, string wmsTaskCode)
        {
            bool success = false;
            if (task.S_TYPE == "深位移库")
            {
                success = TaskProcess.HYCreateTransport(
                task.S_START_LOC,
                task.S_END_LOC,
                task.S_TYPE,
                task.S_CNTR_CODE,
                wmsTaskCode,
                task.N_PRIORITY);
                return  success;
            }
            var relevancy = Settings.OutRelevancys.FirstOrDefault(s => s.conLoc == task.S_END_LOC);
            if (relevancy == null)
            {
                LogHelper.Info($"Settings未查询到集货位{task.S_END_LOC}对应的分拣位!", "杭氧");
                return false;
            }
            // 尝试使用分拣位
            var emptyLoc = LocationHelper.GetLocListEmptyFree(relevancy.sorLoc.ToList()).FirstOrDefault();
            if (emptyLoc != null)
            {
                success = TaskProcess.HYCreateTransport(
                task.S_START_LOC,
                emptyLoc.S_CODE,
                task.S_TYPE,
                task.S_CNTR_CODE,
                wmsTaskCode,
                task.N_PRIORITY);
                if (success && task.S_TYPE != "深位移库")
                {
                    UpdateDistributionCntrState(1, 2, task.S_CNTR_CODE);
                }
            }
            return success;
        }
        /// <summary>
        /// 生成TPLKQ的配盘任务
        /// </summary>
        /// <param name="task"></param>
        /// <param name="wmsTaskCode"></param>
        /// <returns></returns>
        private static bool ProcessNormalTransportTask(WCSTask task, string wmsTaskCode)
        {
            var relevancy = Settings.OutRelevancys.FirstOrDefault(s => s.conLoc == task.S_END_LOC);
            if (relevancy == null)
            {
                LogHelper.Info($"Settings未查询到集货位{task.S_END_LOC}对应的分拣位!", "杭氧");
                return false;
            }
            // 尝试使用分拣位
            var emptyLoc = LocationHelper.GetLocListEmptyFree(relevancy.sorLoc.ToList()).FirstOrDefault();
            if (emptyLoc != null)
            {
                return CreateAndLogTransport(
                    task.S_START_LOC,
                    emptyLoc.S_CODE,
                    task.S_TYPE,
                    task.S_CNTR_CODE,
                    wmsTaskCode,
                    task.N_PRIORITY);
            }
            // 尝试使用拣选缓存区
            var reservoir = Settings.ReservoirAreas.FirstOrDefault(s => s.areaName == "拣选缓存区");
            if (reservoir == null) return false;
            var lxLocation = LocationHelper.GetLocAreaList(reservoir.areaCode).FirstOrDefault();
            if (lxLocation == null) return false;
            return CreateAndLogTransport(
                task.S_START_LOC,
                lxLocation.S_CODE,
                "配盘缓存",
                task.S_CNTR_CODE,
                wmsTaskCode,
                task.N_PRIORITY);
        }
        private static bool CreateAndLogTransport(string startLoc, string endLoc, string taskType,
            string cntrCode, string wmsTaskCode, int priority)
        {
            var success = TaskProcess.HYCreateTransport(
                startLoc, endLoc, taskType, cntrCode, wmsTaskCode, priority);
            if (success)
            {
                UpdateDistributionCntrState(1, 2, cntrCode);
            }
            else
            {
                LogHelper.Info("根据配盘单生成出库任务创建出库任务失败!!");
            }
            return success;
        }
        private static void LogErrorWithStackTrace(string message, Exception ex)
        {
            var st = new StackTrace(ex, true);
            var frame = st.GetFrame(0);
            if (frame == null) return;
            LogHelper.Error($"{message}{ex.Message}!!", ex);
            LogHelper.Error($"文件名: {frame.GetFileName()}", ex);
            LogHelper.Error($"行号: {frame.GetFileLineNumber()}", ex);
            LogHelper.Error($"列号: {frame.GetFileColumnNumber()}", ex);
        }
        #endregion