刘磊
2024-12-21 a6ea79849f0142b5280f0c5d4b15ecc83f0d015a
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_StorageTaskServices/Task/Dt_TaskService.cs
@@ -1,20 +1,13 @@

using AngleSharp.Io;
using log4net.Core;
using AngleSharp.Io;
using Mapster;
using Masuit.Tools;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using SixLabors.Fonts.Tables.AdvancedTypographic;
using System.Text.RegularExpressions;
using WIDESEA_Core.Const;
using WIDESEA_DTO.MOM;
using WIDESEA_DTO.WMS;
using WIDESEA_IServices;
using WIDESEA_IStoragIntegrationServices;
using WIDESEA_Model.Models;
using WIDESEA_Services;
using WIDESEA_StorageBasicRepository;
using WIDESEAWCS_BasicInfoRepository;
using WIDESEAWCS_Model.Models;
namespace WIDESEA_StorageTaskServices;
@@ -76,7 +69,6 @@
    #region 出库任务完成
    public async Task<WebResponseContent> CompleteStackTaskAsync(Dt_Task task, DtStockInfo stock)
    {
        WebResponseContent content = new WebResponseContent();
@@ -87,7 +79,7 @@
                //var process = await SqlSugarHelper.Db.Queryable<Dt_EquipmentProcess>()
                //    .FirstAsync(x => x.EquipmentName == task.Roadway);
                //var info = JsonConvert.DeserializeObject<ResponseEqptRunDto>(process.ProcessValue);
                if (!task.Roadway.Contains("FR"))  //非分容库区均上报MOM出入站
                if (!task.Roadway.Contains("FR") && stock.ProcessCode != "OCVB")  //非分容库区与当前工序是OCVB均上报MOM出入站
                {
                    var agingOutputDto = MapToAgingOutputDto(stock);
                    content = await _agingInOrOutInputService.GetOCVOutputAsync(agingOutputDto);
@@ -164,13 +156,13 @@
            {
                SlotNo = x.OrderNo.ToInt32(),
                SerialNo = x.SerialNumber,
                SerialNoResult = isNG,
                SerialNoResult = true, //isNG,
                ParameterInfo = new List<ParameterInfoOutput> {
                    new ParameterInfoOutput() {
                        Value = outHours.ToString(),
                        ParameterCode =parameterInfo.ParameterCode,
                        ParameterDesc = parameterInfo.Description,
                        ParameterResult  = isNG.ToString(),
                        ParameterResult  = "OK", //isNG.ToString(),
                        TargetValue = parameterInfo.TargetValue,
                        LowerLomit = parameterInfo.LowerSpecificationsLimit,
                        UpperLimit = parameterInfo.UpperSpecificationsLimit,
@@ -184,7 +176,6 @@
    private void ValidateResponse(WebResponseContent content)
    {
    }
    private (DtLocationInfo, Dt_Task) UpdateStockAndTaskStatus(DtStockInfo stock, Dt_Task task)
@@ -262,12 +253,12 @@
        try
        {
            // 更新货位和库存信息
            (DtStockInfo updateStock, DtLocationInfo locationInf) = UpdateStockLocation(stock, task.NextAddress);
            (DtStockInfo updateStock, DtLocationInfo locationInForm, DtLocationInfo locationInfoTo) = UpdateStockLocation(stock, task);
            var taskHty = CreateHistoricalTask(task);
            LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"货位地址:{task.TargetAddress},修改后库存数据:{JsonConvert.SerializeObject(updateStock)},原先货位数据:{locationInf}");
            LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"货位地址:{task.TargetAddress},修改后库存数据:{JsonConvert.SerializeObject(updateStock)},原先货位数据:{locationInForm}");
            // 执行数据库事务
            bool isResult = await ExecuteTransaction(updateStock, taskHty, locationInf, task.TaskId);
            bool isResult = await ExecuteTransaction(updateStock, taskHty, locationInForm, locationInfoTo, task.TaskId);
            if (isResult)
                content.OK("移库任务完成成功");
            else
@@ -304,7 +295,6 @@
                // 执行数据库事务
                await _unitOfWorkManage.UseTranAsync(async () =>
                {
                    // 添加历史任务
                    var isTaskHtyAdd = await _task_HtyRepository.AddDataAsync(taskHtyNG) > 0;
@@ -326,9 +316,15 @@
            // 创建历史任务实例模型
            var taskHty = CreateHistoricalTask(task);
            if (task.TaskType == (int)TaskInboundTypeEnum.InQuality)
            {
                await _locationRepository.UpdateDataAsync(locationInf);
                await _task_HtyRepository.AddDataAsync(taskHty);
                await BaseDal.DeleteDataAsync(task);
                return content.OK("入库任务完成成功");
            }
            // 根据是否有组盘信息创建库存实例模型
            DtStockInfo stock = boxing == null ? CreateEmptyPalletStock(task, locationInf) : CreateFullPalletStock(task, locationInf, boxing);
            // 执行数据库事务
            bool isResult = await ExecuteTransaction(stock, taskHty, locationInf, task.TaskId, boxing);
@@ -423,15 +419,23 @@
        }
        else
        {
            var station = _stationManagerRepository.QueryFirst(x => x.stationChildCode == task.SourceAddress);
            if (station.stationPLC == "1017")
                area = _areaInfoRepository.QueryFirst(x => x.AreaID == Convert.ToInt32(station.stationNGLocation));
            else
                area = _areaInfoRepository.QueryFirst(x => x.AreaID == loation.AreaId);
            //var station = _stationManagerRepository.QueryFirst(x => x.stationChildCode == task.SourceAddress);
            //if (station.stationPLC == "1017")
            //    area = _areaInfoRepository.QueryFirst(x => x.AreaID == Convert.ToInt32(station.stationNGLocation));
            //else
            //    area = _areaInfoRepository.QueryFirst(x => x.AreaID == loation.AreaId);
            //if (area == null)
            //    throw new Exception("未找到对应区域信息");
            if (boxing.ProcessCode == "OCV1")
                area = _areaInfoRepository.QueryFirst(x => x.AreaID == 6);
            else if (boxing.ProcessCode == "OCVB")
                area = _areaInfoRepository.QueryFirst(x => x.AreaID == 7);
            if (area == null)
                throw new Exception("未找到对应区域信息");
        }
        var boxDetail = boxing.BoxingInfoDetails.Adapt<List<DtStockInfoDetail>>();
        boxDetail.ForEach(x => { x.Status = (int)StockStateEmun.已入库; });
@@ -445,29 +449,51 @@
            AreaCode = area.AreaCode,
            LocationId = loation.Id,
            StockInfoDetails = boxDetail,
            ProcessCode = boxing.ProcessCode,
            NextProcessCode = boxing.NextProcessCode,
            Remark = boxing.BoxingInfoDetails.Count().ToString(),
        };
        // 处理请求参数
        AgingInputDto agingInputDto = new AgingInputDto()
        if (boxing.ProcessCode != "OCVB")
        {
            SerialNos = boxing.BoxingInfoDetails
                .Select(item => new SerialNoInDto { SerialNo = item.SerialNumber, PositionNo = item.OrderNo })
                .ToList(),
            TrayBarcode = task.PalletCode,
            OpFlag = 1,
            EquipmentCode = area.Spare2,
            Software = area.Spare3
        };
            // 处理请求参数
            AgingInputDto agingInputDto = new AgingInputDto()
            {
                SerialNos = boxing.BoxingInfoDetails
                    .Select(item => new SerialNoInDto { SerialNo = item.SerialNumber, PositionNo = item.OrderNo })
                    .ToList(),
                TrayBarcode = task.PalletCode,
                OpFlag = 1,
                EquipmentCode = area.Spare2,
                Software = area.Spare3
            };
        var result = _agingInOrOutInputService.GetOCVInputAsync(agingInputDto).Result;
        var respone = JsonConvert.DeserializeObject<ResponeAgingInputDto>(result.Data.ToString());
        stock.LinedProcessFeedbackTime = respone.LinedProcessFeedbackTime;
        stock.SpecialParameterDuration = respone.SpecialParameterDuration;
        //2024年11月16日:新增字段计算应出库时间
        stock.OutboundTime = Convert.ToDateTime(respone.LinedProcessFeedbackTime == null ? DateTime.Now : respone.LinedProcessFeedbackTime).AddHours(Convert.ToDouble(respone.SpecialParameterDuration));
        stock.ProductionLine = respone.ProductionLine;
        stock.ParameterInfos = respone.ParameterInfos.ToJsonString();
        stock.StockStatus = 1;
            var result = _agingInOrOutInputService.GetOCVInputAsync(agingInputDto).Result;
            var respone = JsonConvert.DeserializeObject<ResponeAgingInputDto>(result.Data.ToString());
            bool isFull = false;
            if (!task.Roadway.Contains("FR"))
            {
                isFull = respone.SpecialParameterDuration.IsNullOrEmpty();
            }
            if (respone.ProductionLine == null || respone.ParameterInfos == null)
            {
                throw new Exception("MOM数据返回错误");
            }
            stock.LinedProcessFeedbackTime = respone.LinedProcessFeedbackTime;
            stock.SpecialParameterDuration = respone.SpecialParameterDuration;
            //2024年11月16日:新增字段计算应出库时间
            stock.OutboundTime = Convert.ToDateTime(respone.LinedProcessFeedbackTime == null ? DateTime.Now : respone.LinedProcessFeedbackTime).AddHours(Convert.ToDouble(respone.SpecialParameterDuration));
            stock.ProductionLine = respone.ProductionLine;
            stock.ParameterInfos = respone.ParameterInfos.ToJsonString();
            stock.StockStatus = 1;
        }
        else
        {
            stock.OutboundTime = DateTime.Now;
            stock.StockStatus = 1;
            stock.ProductionLine = boxing.ProductionLine;
        }
        // 记录日志
        LogFactory.GetLog("任务完成").InfoFormat(true, "入库任务完成", $"货位地址:{task.TargetAddress},修改后货位数据:{locationInf}");
@@ -522,6 +548,9 @@
                LogFactory.GetLog("任务完成").InfoFormat(true, "出库任务", "");
                return await CompleteStackTaskAsync(task, stock);
            case (int)TaskRelocationTypeEnum.Relocation:
                return await CompleteTransferTaskAsync(task, stock);
            default:
                return content.Error("任务类型不存在");
        }
@@ -532,6 +561,7 @@
    #region 请求任务入库
    #region
    /// <summary>
    /// 请求任务巷道
    /// </summary>
@@ -566,7 +596,6 @@
                    return content.OK(data: taskDTO);
                }
            }
            var stock = await _stockInfoRepository.QueryFirstNavAsync(x => x.PalletCode == input.PalletCode && x.IsFull);
            if (stock != null)
@@ -719,18 +748,23 @@
                    case "CH01":
                        areaIn = "CH001";
                        break;
                    case "JZ01":
                        areaIn = "JZ001";
                        break;
                    case "GW01":
                        areaIn = "GWSC1";
                        break;
                    case "CW01":
                        areaIn = "CWSC1";
                        break;
                    case "CW02":
                        areaIn = "CWSC2";
                        break;
                    default:
                        break;
                }
@@ -762,7 +796,7 @@
        return content;
    }
    #endregion
    #endregion 请求任务入库
    public async Task<WebResponseContent> RequestTaskAsync(RequestTaskDto input)
    {
@@ -793,7 +827,7 @@
                    PalletCode = stock.PalletCode,
                    SourceAddress = input.Position,
                    CurrentAddress = input.Position,
                    TaskState = (int)TaskInStatusEnum.InNew,
                    TaskState = stock.LocationInfo.RoadwayNo.Contains("CH") ? (int)TaskInStatusEnum.InNew : (int)TaskInStatusEnum.Line_InFinish,
                    TaskType = (int)TaskInboundTypeEnum.InQuality,
                    TaskNum = BaseDal.GetTaskNo().Result,
                    Creater = "System", // 修正拼写错误
@@ -801,12 +835,15 @@
                    TaskId = 0,
                };
                var taskDTO = CreateTaskDTO(task);
                var taskDTO = CreateTaskDTO(taskNew);
                BaseDal.AddData(taskNew);
                return content.OK(data: taskDTO);
                // TODO质检回库
            }
            // 根据位置查询区域信息
            var area = await QueryAreaInfoByPosition(input.Position.Replace("-1", ""));
            var areaCode = Regex.Replace(input.Position, @"-(\d+)", "");
            var area = await QueryAreaInfoByPosition(areaCode);
            if (area == null)
            {
                return content.Error("该点位不在区域列表中存在");
@@ -823,7 +860,15 @@
                if (result.SerialNos.Count <= 0)
                {
                    // 空托盘入库逻辑
                    return await RequestTrayInTaskAsync(input);
                    var staion = _stationManagerRepository.QueryFirst(x => x.stationChildCode == input.Position && x.stationType == 1 && x.remark == "IN");
                    if (staion != null)
                    {
                        return await HandleErrorCells(input, area);
                    }
                    else
                    {
                        return await RequestTrayInTaskAsync(input);
                    }
                }
                else
                    return content.Error(result.MOMMessage);
@@ -835,7 +880,6 @@
            {
                return await HandleErrorCells(input, area, serialNosError);
            }
            var boxing = CreateBoxingInfo(result, input.PalletCode);
            if (boxing == null) return content.Error("组盘失败");
@@ -851,6 +895,7 @@
        return content;
    }
    /// <summary>
    /// 更新任务货位
    /// </summary>
@@ -866,11 +911,9 @@
                return content.Error($"暂未找到【{input.PalletCode}】的任务");
            return content = await UpdateExistingTask(input, task);
        }
        catch (Exception err)
        {
            throw;
        }
    }
@@ -885,7 +928,6 @@
        WebResponseContent content = new WebResponseContent();
        try
        {
            // 调用BaseDal.QueryFirstAsync方法,查询任务
            var task = await BaseDal.QueryFirstAsync(x => x.PalletCode == input.PalletCode);
            if (task != null && task.TaskState == (int)TaskInStatusEnum.InNew)
@@ -906,7 +948,6 @@
                return content.OK(data: task);
            }
            var stationManagers = _stationManagerRepository.QueryData(x => x.stationType == 6 && x.stationChildCode == input.Position).FirstOrDefault();
            if (stationManagers == null)
            {
@@ -921,7 +962,6 @@
        }
        catch (Exception)
        {
            throw;
        }
    }
@@ -941,6 +981,7 @@
            PalletCode = palletCode,
            IsFull = true,
            ProcessCode = result.ProcessCode,
            ProductionLine = result.ProductionLine,
            BoxingInfoDetails = result.SerialNos.Select(serialNoObj => new DtBoxingInfoDetail
            {
                SerialNumber = serialNoObj.SerialNo,
@@ -966,7 +1007,7 @@
        };
    }
    #endregion 请求任务入库
    #endregion 外部接口方法
    #region 请求出库(实盘&空盘)
@@ -978,15 +1019,15 @@
    /// <param name="areaCode">区域编码</param>
    /// <param name="roadways">巷道编码集合</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> RequestTrayOutTaskAsync(string position, int tag, string areaCode, List<string> roadways)
    public async Task<WebResponseContent> RequestTrayOutTaskAsync(string position, int tag, string areaCode, List<string> areaCodes, string productionLine)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            // 根据托盘类型查询库存信息
            DtStockInfo stockInfo = tag == (int)TaskOutboundTypeEnum.Outbound
                ? QueryStockInfoForRealTrayAsync(areaCode, roadways).Result
                : QueryStockInfoForEmptyTrayAsync(areaCode, roadways).Result;
                ? areaCodes == null ? await QueryStockInfoForRealTrayAsync(areaCode, productionLine) : await QueryStockInfoForRealTrayCWAsync(areaCodes, productionLine)
                : await QueryStockInfoForEmptyTrayAsync(areaCode);
            if (stockInfo == null)
            {
@@ -1033,7 +1074,7 @@
    /// <summary>
    /// 查询实盘库存信息
    /// </summary>
    private async Task<DtStockInfo> QueryStockInfoForRealTrayAsync(string areaCode, List<string> roadways)
    private async Task<DtStockInfo> QueryStockInfoForRealTrayAsync(string areaCode, string productionLine)
    {
        var area = await _areaInfoRepository.QueryFirstAsync(x => x.AreaCode == areaCode);
@@ -1041,6 +1082,29 @@
            .Includes(x => x.LocationInfo) // 预加载LocationInfo
            .Includes(x => x.StockInfoDetails) // 预加载StockInfoDetails
            .Where(x => x.AreaCode == areaCode && x.OutboundTime < DateTime.Now && x.IsFull == true) // 过滤条件
            .WhereIF(!productionLine.IsNullOrEmpty(), x => x.ProductionLine == productionLine)
            .Where(x => x.LocationInfo.LocationStatus == (int)LocationEnum.InStock && x.LocationInfo.AreaId == area.AreaID) // 过滤条件
            .OrderBy(x => x.OutboundTime) // 排序
            .FirstAsync(); // 获取第一个元素
        //var firstOrDefault = result.FirstOrDefault(x => roadways.Contains(x.LocationInfo.RoadwayNo)); // 查找第一个匹配的元素
        //var firstOrDefault = result[0]; // 查找第一个匹配的元素
        //return firstOrDefault;
        return result;
    }
    /// <summary>
    /// 查询实盘库存信息
    /// </summary>
    private async Task<DtStockInfo> QueryStockInfoForRealTrayCWAsync(List<string> areaCodes, string productionLine)
    {
        var area = await _areaInfoRepository.QueryFirstAsync(x => x.AreaCode == "CWSC1");
        var result = await _stockInfoRepository.Db.Queryable<DtStockInfo>()
            .Includes(x => x.LocationInfo) // 预加载LocationInfo
            .Includes(x => x.StockInfoDetails) // 预加载StockInfoDetails
            .Where(x => areaCodes.Contains(x.AreaCode) && x.OutboundTime < DateTime.Now && x.IsFull == true) // 过滤条件
            .WhereIF(!productionLine.IsNullOrEmpty(), x => x.ProductionLine == productionLine)
            .Where(x => x.LocationInfo.LocationStatus == (int)LocationEnum.InStock && x.LocationInfo.AreaId == area.AreaID) // 过滤条件
            .OrderBy(x => x.OutboundTime) // 排序
            .FirstAsync(); // 获取第一个元素
@@ -1054,7 +1118,7 @@
    /// <summary>
    /// 查询空盘库存信息
    /// </summary>
    private async Task<DtStockInfo> QueryStockInfoForEmptyTrayAsync(string areaCode, List<string> roadways)
    private async Task<DtStockInfo> QueryStockInfoForEmptyTrayAsync(string areaCode)
    {
        var area = await _areaInfoRepository.QueryFirstAsync(x => x.AreaCode == areaCode);
@@ -1117,7 +1181,7 @@
        };
    }
    #endregion 请求出库
    #endregion 请求出库(实盘&空盘)
    #region 任务状态更改
@@ -1167,34 +1231,7 @@
        return content;
    }
    #endregion
    #region 出库解盘
    /// <summary>
    /// 出库解盘接口
    /// </summary>
    /// <param name="taskNum"></param>
    /// <returns></returns>
    public async Task<WebResponseContent> OutUnblockInterface(int taskNum)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var task = await BaseDal.QueryFirstAsync(x => x.TaskNum == taskNum);
            if (task == null)
                return content.Error("未找到任务");
            task.TaskState = (int)TaskOutStatusEnum.Line_OutFinish;
            var taskHty = CreateHistoricalTask(task);
        }
        catch (Exception ex)
        {
            content.Error(ex.Message);
        }
        return content;
    }
    #endregion
    #endregion 任务状态更改
    #region 指定任务出库
@@ -1221,8 +1258,19 @@
                taskType = (int)TaskOutboundTypeEnum.OutQuality;
            else
                taskType = (int)TaskOutboundTypeEnum.OutTray;
            // 创建并添加任务到数据库
            task = CreateTask(stockInfo, "1020-1", taskType);
            if (stockInfo.AreaCode.Contains("CH"))
            {
                // 创建并添加任务到数据库
                task = CreateTask(stockInfo, "1020-1", taskType);
            }
            else
            {
                if (stockInfo.LocationInfo.RoadwayNo == "JZSC1")
                {
                    task = CreateTask(stockInfo, "002-021-001", taskType);
                }
            }
            //var taskId = await BaseDal.AddDataAsync(task);
            //if (taskId <= 0)
            //{
@@ -1260,6 +1308,7 @@
        return content;
    }
    private string GetWCSIpReceiveTask()
    {
        var configs = _configService.GetConfigsByCategory(CateGoryConst.CONFIG_SYS_IPAddress);
@@ -1271,6 +1320,10 @@
        }
        return wmsBase + ipAddress;
    }
    #endregion 指定任务出库
    #region  静置异常口入库
    #endregion
@@ -1449,20 +1502,19 @@
    /// <param name="stock">库存对象</param>
    /// <param name="toLocation">目标位置</param>
    // 更新库存和位置信息
    private (DtStockInfo, DtLocationInfo) UpdateStockLocation(DtStockInfo stock, string toLocation)
    private (DtStockInfo, DtLocationInfo, DtLocationInfo) UpdateStockLocation(DtStockInfo stock, Dt_Task task)
    {
        // 获取库存信息
        var locationInfo = _locationRepository.QueryFirst(x => x.LocationCode == stock.LocationCode);
        // 将库存状态设置为在库
        locationInfo.LocationStatus = LocationEnum.InStock.ObjToInt();
        //修改来源库位和 目标库位状态
        var fromLocation = _locationRepository.QueryFirst(x => x.LocationCode == task.SourceAddress && x.RoadwayNo == task.Roadway);
        fromLocation.LocationStatus = LocationEnum.Free.ObjToInt();
        var toLocation = _locationRepository.QueryFirst(x => x.LocationCode == task.SourceAddress && x.RoadwayNo == task.Roadway);
        toLocation.LocationStatus = LocationEnum.InStock.ObjToInt();
        // 将库存位置设置为目标位置
        stock.LocationCode = toLocation;
        // 将库存状态设置为在库
        stock.LocationInfo.LocationStatus = LocationEnum.InStock.ObjToInt();
        stock.LocationCode = task.TargetAddress;
        // 返回更新后的库存和位置信息
        return (stock, locationInfo);
        return (stock, fromLocation, toLocation);
    }
    /// <summary>
@@ -1494,7 +1546,6 @@
                                            .Include(x => x.BoxingInfoDetails)
                                            .ExecuteCommandAsync();
                }
            }
            var stocks = _stockInfoRepository.QueryData(x => x.AreaCode == stock.AreaCode && x.ProductionLine == stock.ProductionLine && x.SpecialParameterDuration != stock.SpecialParameterDuration);
@@ -1606,7 +1657,6 @@
                _unitOfWorkManage.CommitTran();
                return content.OK(data: task);
            }
        }
        catch (Exception ex)
        {