wanshenmean
9 小时以前 0fa137570bf7ac2bf58c8af2828cd595625fa400
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_AGV.cs
@@ -1,681 +1,678 @@
using Mapster;
using System.Text.Json;
using WIDESEA_Common.Constants;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
using WIDESEA_Common.WareHouseEnum;
using WIDESEA_Core;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Task;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
namespace WIDESEA_TaskInfoService
{
    public partial class TaskService
    {
        public string AGV_OutTaskComplete = WIDESEA_Core.Helper.AppSettings.Configuration["AGV_OutTaskComplete"];
        public string WCS_ReceiveTask = WIDESEA_Core.Helper.AppSettings.Configuration["WCS_ReceiveTask"];
        /// <summary>
        /// 极卷库出入库申请
        /// </summary>
        public async Task<AGVResponse> ApplyInOutAsync(ApplyInOutDto applyInOutDto)
        {
            AGVResponse response = new AGVResponse();
            try
            {
                var validationMessage = ValidateApplyInOutRequest(applyInOutDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var existingTask = await BaseDal.QueryFirstAsync(x => x.PalletCode == applyInOutDto.TrayNumber || x.OrderNo == applyInOutDto.TaskId);
                if (existingTask != null)
                    return response.Error($"WMS已有当前任务,不可重复下发,任务号:{applyInOutDto.TaskId}");
                var task = BuildAgvTask(applyInOutDto);
                if (applyInOutDto.InOut == 1)
                {
                    var inboundResult = await CreateAgvInboundTaskAsync(task, applyInOutDto);
                    if (inboundResult != null)
                        return inboundResult;
                }
                else
                {
                    var outboundResult = await CreateAgvOutboundTaskAsync(task, applyInOutDto);
                    if (outboundResult != null)
                        return outboundResult;
                }
                return response.OK(BuildAgvDataDto(task, applyInOutDto));
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"WMS任务创建接口错误: {ex.Message}");
            }
        }
        /// <summary>
        /// 手动出库完成反馈给AGV
        /// </summary>
        public async Task<WebResponseContent> OutTaskComplete(OutTaskCompleteDto outTaskCompleteDto)
        {
            WebResponseContent response = new WebResponseContent();
            try
            {
                var validationMessage = ValidateOutTaskCompleteRequest(outTaskCompleteDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == outTaskCompleteDto.TaskId);
                if (task == null)
                    return response.Error("未找到任务信息");
                outTaskCompleteDto.ReqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                var httpResponse = _httpClientHelper.Post<AGVResponse>(AGV_OutTaskComplete, outTaskCompleteDto.ToJson()).Data;
                if (httpResponse == null || httpResponse.Data == null)
                    return response.Error(httpResponse?.Msg ?? "AGV接口调用异常");
                if (!httpResponse.Code)
                        return response.Error(string.IsNullOrWhiteSpace(httpResponse.Msg) ? "AGV接口调用失败" : httpResponse.Msg);
                var syncResult = await CompleteLocalOutboundAfterAgvAckAsync(task);
                return syncResult.Status ? response.OK(httpResponse.Msg) : syncResult;
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"WMS任务完成接口错误:{ex.Message}");
            }
        }
        /// <summary>
        /// 输送线申请进入
        /// </summary>
        public async Task<AGVResponse> ApplyEnterAsync(ApplyEnterDto applyEnterDto)
        {
            AGVResponse response = new AGVResponse();
            try
            {
                var validationMessage = ValidateApplyEnterRequest(applyEnterDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == applyEnterDto.TaskId);
                if (task == null)
                    return response.Error($"未找到任务信息,任务号:{applyEnterDto.TaskId}");
                if (CanApplyEnter(task, applyEnterDto))
                    return response.OK();
                return response.Error($"输送线{applyEnterDto.DevId}当前繁忙,请稍后重试");
            }
            catch (Exception ex)
            {
                return response.Error($"WMS输送线申请接口错误:{ex.Message}");
            }
        }
        /// <summary>
        /// 取放货完成
        /// </summary>
        public async Task<AGVResponse> TaskCompleteAsync(TaskCompleteDto taskCompleteDto)
        {
            AGVResponse response = new AGVResponse();
            try
            {
                var validationMessage = ValidateTaskCompleteRequest(taskCompleteDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == taskCompleteDto.TaskId);
                if (task == null)
                    return response.Error($"未找到任务信息,任务号:{taskCompleteDto.TaskId}");
                return taskCompleteDto.InOut == 2
                    ? await CompleteAgvOutboundTaskAsync(task)
                    : await CompleteAgvInboundTaskAsync(task);
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"WMS取放货完成接口错误:{ex.Message}");
            }
        }
        /// <summary>
        /// 任务取消
        /// </summary>
        public async Task<AGVResponse> TaskCancelAsync(TaskCancelDto taskCancelDto)
        {
            AGVResponse response = new AGVResponse();
            try
            {
                var validationMessage = ValidateTaskCancelRequest(taskCancelDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == taskCancelDto.TaskId);
                if (task == null)
                    return response.OK();
                if (task.TaskStatus == (int)TaskInStatusEnum.InNew)
                    return await CancelAgvInboundTask(task);
                if (task.TaskStatus == (int)TaskOutStatusEnum.OutNew)
                    return await CancelAgvOutboundTaskAsync(task);
                return response.Error("任务已经在执行中,不可取消");
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"WMS任务取消接口错误:{ex.Message}");
            }
        }
        #region 参数验证
        private static string? ValidateApplyInOutRequest(ApplyInOutDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.TrayNumber)) return "托盘号不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            if (string.IsNullOrWhiteSpace(dto.MaterialType)) return "物料类型不能为空";
            if (string.IsNullOrWhiteSpace(dto.MaterialName)) return "物料描述不能为空";
            if (string.IsNullOrWhiteSpace(dto.ReqTime)) return "请求时间不能为空";
            if (dto.Floor != 1 && dto.Floor != 2) return $"楼层段错误,必须为1(模切段)或2(卷绕段),当前值:{dto.Floor}";
            if (dto.YinYang != 1 && dto.YinYang != 2) return $"阴阳极错误,必须为1(阴极)或2(阳极),当前值:{dto.YinYang}";
            if (dto.InOut != 1 && dto.InOut != 2) return $"出入库类型错误,必须为1(入库)或2(出库),当前值:{dto.InOut}";
            if (dto.InOut == 1 && (dto.Width == null || dto.Width <= 0)) return "入库时宽度不能为空且必须大于0";
            if (dto.InOut == 1 && string.IsNullOrWhiteSpace(dto.Group)) return "入库时整托组别不能为空";
            return null;
        }
        private static string? ValidateOutTaskCompleteRequest(OutTaskCompleteDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            if (string.IsNullOrWhiteSpace(dto.DevId)) return "出库口编号不能为空";
            return null;
        }
        private static string? ValidateApplyEnterRequest(ApplyEnterDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.DevId)) return "设备编号不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            if (dto.InOut != 1 && dto.InOut != 2) return $"出入库类型错误,必须为1(入库)或2(出库),当前值:{dto.InOut}";
            return null;
        }
        private static string? ValidateTaskCompleteRequest(TaskCompleteDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            if (string.IsNullOrWhiteSpace(dto.DevId)) return "设备编号不能为空";
            if (dto.InOut != 1 && dto.InOut != 2) return $"出入库类型错误,必须为1(入库)或2(出库),当前值:{dto.InOut}";
            return null;
        }
        private static string? ValidateTaskCancelRequest(TaskCancelDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            return null;
        }
        #endregion 参数验证
        #region 具体实现
        // 出入库共用创建任务
        private Dt_Task BuildAgvTask(ApplyInOutDto dto)
        {
            var task = new Dt_Task
            {
                OrderNo = dto.TaskId,
                PalletCode = dto.TrayNumber,
                PalletType = dto.Floor,
                Grade = 1,
                Creater = "AGV",
                CreateDate = DateTime.Now,
                Remark = $"物料类型:{dto.MaterialType},物料描述:{dto.MaterialName}"
            };
            if (dto.YinYang == 1)
            {
                task.Roadway = WarehouseEnum.FJ1.ToString();
                task.WarehouseId = (int)WarehouseEnum.FJ1;
                task.SourceAddress = dto.InOut == 1 ? "D10010" : "D10020";
                task.NextAddress = "D10080";
                task.TargetAddress = "阴极卷库";
            }
            else
            {
                task.Roadway = WarehouseEnum.ZJ1.ToString();
                task.WarehouseId = (int)WarehouseEnum.ZJ1;
                task.SourceAddress = dto.InOut == 1 ? "D10100" : "D10090";
                task.NextAddress = "D10160";
                task.TargetAddress = "正极卷库";
            }
            return task;
        }
        // 构建返回AGV出入库请求体
        private AGVDataDto BuildAgvDataDto(Dt_Task task, ApplyInOutDto dto)
        {
            return new AGVDataDto
            {
                DevId = dto.InOut == 1 ? task.SourceAddress : task.TargetAddress,
                TrayNumber = task.PalletCode,
                Group = dto.Group,
                Width = dto.Width ?? 0,
                LabelNumber = dto.LabelNumber,
                ProductNo = dto.ProductNo,
                ProductName = dto.ProductName,
                Quantity = dto.Quantity,
                UomCode = dto.UomCode,
                ProductType = dto.ProductType,
                Equipment = dto.Equipment,
                ProductionDate = dto.ProductionDate,
                LowerLimitTime = dto.LowerLimitTime,
                WarningTime = dto.WarningTime,
                OverdueTime = dto.OverdueTime
            };
        }
        // 入库创建
        private async Task<AGVResponse?> CreateAgvInboundTaskAsync(Dt_Task task, ApplyInOutDto dto)
        {
            AGVResponse response = new AGVResponse();
            var stockInfo = await _stockInfoService.GetStockInfoAsync(dto.TrayNumber);
            if (stockInfo != null)
                return response.Error($"当前托盘{dto.TrayNumber}已经入库了");
            // 创建库存明细
            var details = new Dt_StockInfoDetail
            {
                MaterielCode = dto.ProductNo,
                MaterielName = dto.ProductName,
                StockQuantity = int.TryParse(dto.Quantity, out int quantity) ? quantity : 0,
                Unit = dto.UomCode,
                OrderNo = dto.ProductNo,
                ProductionDate =dto.ProductionDate,
                EffectiveDate = dto.LowerLimitTime,
                SerialNumber = dto.TrayNumber,
                Status = (int)StockStatusEmun.入库确认,
                InboundOrderRowNo = 1,
                Creater = StockConstants.AGV_USER,
                CreateDate = DateTime.Now,
                Remark = $"AGV入库任务创建,任务号:{dto.TaskId}"
            };
            // 创建库存主记录
            var stock = new Dt_StockInfo
            {
                PalletCode = dto.TrayNumber,
                PalletType = dto.Floor,
                WarehouseId = dto.YinYang == 1 ? (int)WarehouseEnum.FJ1 : (int)WarehouseEnum.ZJ1,
                StockStatus = (int)StockStatusEmun.入库确认,
                Creater = StockConstants.AGV_USER,
                CreateDate = DateTime.Now,
                Remark = $"AGV入库任务创建,任务号:{dto.TaskId}",
                Details = new List<Dt_StockInfoDetail> { details }
            };
            task.TaskType = (int)TaskInboundTypeEnum.Inbound;
            task.TaskStatus = (int)TaskInStatusEnum.InNew;
            task.CurrentAddress = task.SourceAddress;
            _unitOfWorkManage.BeginTran();
            try
            {
                // 先创建任务
                var taskResult = await BaseDal.AddDataAsync(task) > 0;
                if (!taskResult)
                {
                    _unitOfWorkManage.RollbackTran();
                    return response.Error("入库任务创建失败");
using Mapster;
using System.Text.Json;
using WIDESEA_Common.Constants;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
using WIDESEA_Common.WareHouseEnum;
using WIDESEA_Core;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Task;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
namespace WIDESEA_TaskInfoService
{
    public partial class TaskService
    {
        public string AGV_OutTaskComplete = WIDESEA_Core.Helper.AppSettings.Configuration["AGV_OutTaskComplete"];
        public string WCS_ReceiveTask = WIDESEA_Core.Helper.AppSettings.Configuration["WCS_ReceiveTask"];
        /// <summary>
        /// 极卷库出入库申请
        /// </summary>
        public async Task<AGVResponse> ApplyInOutAsync(ApplyInOutDto applyInOutDto)
        {
            AGVResponse response = new AGVResponse();
            try
            {
                var validationMessage = ValidateApplyInOutRequest(applyInOutDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var existingTask = await BaseDal.QueryFirstAsync(x => x.PalletCode == applyInOutDto.TrayNumber || x.OrderNo == applyInOutDto.TaskId);
                if (existingTask != null)
                    return response.Error($"WMS已有当前任务,不可重复下发,任务号:{applyInOutDto.TaskId}");
                var task = BuildAgvTask(applyInOutDto);
                if (applyInOutDto.InOut == 1)
                {
                    var inboundResult = await CreateAgvInboundTaskAsync(task, applyInOutDto);
                    if (inboundResult != null)
                        return inboundResult;
                }
                else
                {
                    var outboundResult = await CreateAgvOutboundTaskAsync(task, applyInOutDto);
                    if (outboundResult != null)
                        return outboundResult;
                }
                return response.OK(BuildAgvDataDto(task, applyInOutDto));
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"WMS任务创建接口错误: {ex.Message}");
            }
        }
        /// <summary>
        /// 手动出库完成反馈给AGV
        /// </summary>
        public async Task<WebResponseContent> OutTaskComplete(OutTaskCompleteDto outTaskCompleteDto)
        {
            WebResponseContent response = new WebResponseContent();
            try
            {
                var validationMessage = ValidateOutTaskCompleteRequest(outTaskCompleteDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == outTaskCompleteDto.TaskId);
                if (task == null)
                    return response.Error("未找到任务信息");
                outTaskCompleteDto.ReqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                var httpResponse = _httpClientHelper.Post<AGVResponse>(AGV_OutTaskComplete, outTaskCompleteDto.ToJson()).Data;
                if (httpResponse == null || httpResponse.Data == null)
                    return response.Error(httpResponse?.Msg ?? "AGV接口调用异常");
                if (!httpResponse.Code)
                        return response.Error(string.IsNullOrWhiteSpace(httpResponse.Msg) ? "AGV接口调用失败" : httpResponse.Msg);
                var syncResult = await CompleteLocalOutboundAfterAgvAckAsync(task);
                return syncResult.Status ? response.OK(httpResponse.Msg) : syncResult;
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"WMS任务完成接口错误:{ex.Message}");
            }
        }
        /// <summary>
        /// 输送线申请进入
        /// </summary>
        public async Task<AGVResponse> ApplyEnterAsync(ApplyEnterDto applyEnterDto)
        {
            AGVResponse response = new AGVResponse();
            try
            {
                var validationMessage = ValidateApplyEnterRequest(applyEnterDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == applyEnterDto.TaskId);
                if (task == null)
                    return response.Error($"未找到任务信息,任务号:{applyEnterDto.TaskId}");
                if (CanApplyEnter(task, applyEnterDto))
                    return response.OK();
                return response.Error($"输送线{applyEnterDto.DevId}当前繁忙,请稍后重试");
            }
            catch (Exception ex)
            {
                return response.Error($"WMS输送线申请接口错误:{ex.Message}");
            }
        }
        /// <summary>
        /// 取放货完成
        /// </summary>
        public async Task<AGVResponse> TaskCompleteAsync(TaskCompleteDto taskCompleteDto)
        {
            AGVResponse response = new AGVResponse();
            try
            {
                var validationMessage = ValidateTaskCompleteRequest(taskCompleteDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == taskCompleteDto.TaskId);
                if (task == null)
                    return response.Error($"未找到任务信息,任务号:{taskCompleteDto.TaskId}");
                return taskCompleteDto.InOut == 2
                    ? await CompleteAgvOutboundTaskAsync(task)
                    : await CompleteAgvInboundTaskAsync(task);
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"WMS取放货完成接口错误:{ex.Message}");
            }
        }
        /// <summary>
        /// 任务取消
        /// </summary>
        public async Task<AGVResponse> TaskCancelAsync(TaskCancelDto taskCancelDto)
        {
            AGVResponse response = new AGVResponse();
            try
            {
                var validationMessage = ValidateTaskCancelRequest(taskCancelDto);
                if (validationMessage != null)
                    return response.Error(validationMessage);
                var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == taskCancelDto.TaskId);
                if (task == null)
                    return response.OK();
                if (task.TaskStatus == (int)TaskInStatusEnum.InNew)
                    return await CancelAgvInboundTask(task);
                if (task.TaskStatus == (int)TaskOutStatusEnum.OutNew)
                    return await CancelAgvOutboundTaskAsync(task);
                return response.Error("任务已经在执行中,不可取消");
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"WMS任务取消接口错误:{ex.Message}");
            }
        }
        #region 参数验证
        private static string? ValidateApplyInOutRequest(ApplyInOutDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.TrayNumber)) return "托盘号不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            if (string.IsNullOrWhiteSpace(dto.MaterialType)) return "物料类型不能为空";
            if (string.IsNullOrWhiteSpace(dto.MaterialName)) return "物料描述不能为空";
            if (string.IsNullOrWhiteSpace(dto.ReqTime)) return "请求时间不能为空";
            if (dto.Floor != 1 && dto.Floor != 2) return $"楼层段错误,必须为1(模切段)或2(卷绕段),当前值:{dto.Floor}";
            if (dto.YinYang != 1 && dto.YinYang != 2) return $"阴阳极错误,必须为1(阴极)或2(阳极),当前值:{dto.YinYang}";
            if (dto.InOut != 1 && dto.InOut != 2) return $"出入库类型错误,必须为1(入库)或2(出库),当前值:{dto.InOut}";
            if (dto.InOut == 1 && (dto.Width == null || dto.Width <= 0)) return "入库时宽度不能为空且必须大于0";
            if (dto.InOut == 1 && string.IsNullOrWhiteSpace(dto.Group)) return "入库时整托组别不能为空";
            return null;
        }
        private static string? ValidateOutTaskCompleteRequest(OutTaskCompleteDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            if (string.IsNullOrWhiteSpace(dto.DevId)) return "出库口编号不能为空";
            return null;
        }
        private static string? ValidateApplyEnterRequest(ApplyEnterDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.DevId)) return "设备编号不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            if (dto.InOut != 1 && dto.InOut != 2) return $"出入库类型错误,必须为1(入库)或2(出库),当前值:{dto.InOut}";
            return null;
        }
        private static string? ValidateTaskCompleteRequest(TaskCompleteDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            if (string.IsNullOrWhiteSpace(dto.DevId)) return "设备编号不能为空";
            if (dto.InOut != 1 && dto.InOut != 2) return $"出入库类型错误,必须为1(入库)或2(出库),当前值:{dto.InOut}";
            return null;
        }
        private static string? ValidateTaskCancelRequest(TaskCancelDto dto)
        {
            if (dto == null) return "请求参数不能为空";
            if (string.IsNullOrWhiteSpace(dto.TaskId)) return "任务号不能为空";
            return null;
        }
        #endregion 参数验证
        #region 具体实现
        // 出入库共用创建任务
        private Dt_Task BuildAgvTask(ApplyInOutDto dto)
        {
            var task = new Dt_Task
            {
                OrderNo = dto.TaskId,
                PalletCode = dto.TrayNumber,
                PalletType = dto.Floor,
                Grade = 1,
                Creater = "AGV",
                CreateDate = DateTime.Now,
                Remark = $"物料类型:{dto.MaterialType},物料描述:{dto.MaterialName}"
            };
            if (dto.YinYang == 1)
            {
                task.Roadway = WarehouseEnum.FJ1.ToString();
                task.WarehouseId = (int)WarehouseEnum.FJ1;
                task.SourceAddress = dto.InOut == 1 ? "D10010" : "D10020";
                task.NextAddress = "D10080";
                task.TargetAddress = "阴极卷库";
            }
            else
            {
                task.Roadway = WarehouseEnum.ZJ1.ToString();
                task.WarehouseId = (int)WarehouseEnum.ZJ1;
                task.SourceAddress = dto.InOut == 1 ? "D10100" : "D10090";
                task.NextAddress = "D10160";
                task.TargetAddress = "正极卷库";
            }
            return task;
        }
        // 构建返回AGV出入库请求体
        private AGVDataDto BuildAgvDataDto(Dt_Task task, ApplyInOutDto dto)
        {
            return new AGVDataDto
            {
                DevId = dto.InOut == 1 ? task.SourceAddress : task.TargetAddress,
                TrayNumber = task.PalletCode,
                Group = dto.Group,
                Width = dto.Width ?? 0,
                LabelNumber = dto.LabelNumber,
                ProductNo = dto.ProductNo,
                ProductName = dto.ProductName,
                Quantity = dto.Quantity,
                UomCode = dto.UomCode,
                ProductType = dto.ProductType,
                Equipment = dto.Equipment,
                ProductionDate = dto.ProductionDate,
                LowerLimitTime = dto.LowerLimitTime,
                WarningTime = dto.WarningTime,
                OverdueTime = dto.OverdueTime
            };
        }
        // 入库创建
        private async Task<AGVResponse?> CreateAgvInboundTaskAsync(Dt_Task task, ApplyInOutDto dto)
        {
            AGVResponse response = new AGVResponse();
            var stockInfo = await _stockInfoService.GetStockInfoAsync(dto.TrayNumber);
            if (stockInfo != null)
                return response.Error($"当前托盘{dto.TrayNumber}已经入库了");
            // 创建库存明细
            var details = new Dt_StockInfoDetail
            {
                MaterielCode = dto.ProductNo,
                MaterielName = dto.ProductName,
                StockQuantity = int.TryParse(dto.Quantity, out int quantity) ? quantity : 0,
                Unit = dto.UomCode,
                OrderNo = dto.ProductNo,
                ProductionDate =dto.ProductionDate,
                EffectiveDate = dto.LowerLimitTime,
                SerialNumber = dto.TrayNumber,
                Status = (int)StockStatusEmun.入库确认,
                InboundOrderRowNo = 1,
                Creater = StockConstants.AGV_USER,
                CreateDate = DateTime.Now,
                Remark = $"AGV入库任务创建,任务号:{dto.TaskId}"
            };
            // 创建库存主记录
            var stock = new Dt_StockInfo
            {
                PalletCode = dto.TrayNumber,
                PalletType = dto.Floor,
                WarehouseId = dto.YinYang == 1 ? (int)WarehouseEnum.FJ1 : (int)WarehouseEnum.ZJ1,
                StockStatus = (int)StockStatusEmun.入库确认,
                Creater = StockConstants.AGV_USER,
                CreateDate = DateTime.Now,
                Remark = $"AGV入库任务创建,任务号:{dto.TaskId}",
                Details = new List<Dt_StockInfoDetail> { details }
            };
            task.TaskType = (int)TaskInboundTypeEnum.Inbound;
            task.TaskStatus = (int)TaskInStatusEnum.InNew;
            task.CurrentAddress = task.SourceAddress;
            _unitOfWorkManage.BeginTran();
            try
            {
                // 先创建任务
                var taskResult = await BaseDal.AddDataAsync(task) > 0;
                if (!taskResult)
                {
                    _unitOfWorkManage.RollbackTran();
                    return response.Error("入库任务创建失败");
                }
                var result = _stockInfoService.Repository.AddData(stock, x => x.Details);
                if (result)
                {
                    _unitOfWorkManage.CommitTran();
                    return null;
                {
                    _unitOfWorkManage.CommitTran();
                    return null;
                }
                else
                {
                    _unitOfWorkManage.RollbackTran();
                    return response.Error("库存信息创建失败");
                else
                {
                    _unitOfWorkManage.RollbackTran();
                    return response.Error("库存信息创建失败");
                }
                // 使用库存服务添加库存主记录和明细
                //var stockResult = await _stockInfoService.AddStockWithDetailsUsingTransactionAsync(stock);
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"入库任务创建异常:{ex.Message}");
            }
        }
        // 出库创建
        private async Task<AGVResponse?> CreateAgvOutboundTaskAsync(Dt_Task task, ApplyInOutDto dto)
        {
            AGVResponse response = new AGVResponse();
            // 检查库存是否存在
            var stockInfo = await _stockInfoService.GetStockInfoAsync(dto.TrayNumber);
            if (stockInfo == null)
                return response.Error($"未找到托盘{dto.TrayNumber}的库存信息");
            // 检查库存是否有明细(即是否真的有库存)
            if (stockInfo.Details == null || !stockInfo.Details.Any())
                return response.Error($"托盘{dto.TrayNumber}没有库存明细,无法出库");
            // 检查库存总数量是否大于0
            var totalQuantity = stockInfo.Details.Sum(d => d.StockQuantity);
            if (totalQuantity <= 0)
                return response.Error($"托盘{dto.TrayNumber}库存数量不足,无法出库");
            // 根据dto参数进一步验证库存信息
            if (!string.IsNullOrEmpty(dto.ProductNo))
            {
                // 检查库存明细中是否包含指定的物料编码
                var hasMatchingMaterial = stockInfo.Details.Any(d => d.MaterielCode == dto.ProductNo);
                if (!hasMatchingMaterial)
                    return response.Error($"托盘{dto.TrayNumber}中没有物料编码为{dto.ProductNo}的库存,无法出库");
            }
            // 检查库存状态是否允许出库
            if (stockInfo.StockStatus != (int)StockStatusEmun.入库完成)
                return response.Error($"托盘{dto.TrayNumber}正在移动中,请稍后!");
            // 检查货位信息
            var locationInfo = await _locationInfoService.GetLocationInfo(stockInfo.LocationCode);
            if (locationInfo == null)
                return response.Error($"未找到托盘{stockInfo.LocationCode}的货位信息");
            // 检查货位状态是否允许出库
            if (locationInfo.LocationStatus != (int)LocationStatusEnum.InStock)
                return response.Error($"当前货位{locationInfo.LocationStatus}状态信息错误");
            // 验证仓库ID是否匹配(根据dto的阴阳极参数)
            var expectedWarehouseId = dto.YinYang == 1 ? (int)WarehouseEnum.FJ1 : (int)WarehouseEnum.ZJ1;
            if (stockInfo.WarehouseId != expectedWarehouseId)
                return response.Error($"托盘{dto.TrayNumber}不在预期的仓库中,无法出库");
            task.TaskType = (int)TaskOutboundTypeEnum.Outbound;
            task.TaskStatus = (int)TaskOutStatusEnum.OutNew;
            task.SourceAddress = stockInfo.LocationCode;
            task.CurrentAddress = stockInfo.LocationCode;
            task.TargetAddress = dto.YinYang == 1 ? "D10020" : "D10090";
            var wmsTaskDto = _mapper.Map<WMSTaskDTO>(task);
            var taskList = new List<WMSTaskDTO> { wmsTaskDto };
            var requestBody = JsonSerializer.Serialize(taskList);
            var httpResponse = _httpClientHelper.Post<WebResponseContent>(WCS_ReceiveTask, requestBody);
            if (httpResponse == null || httpResponse.Data == null || !httpResponse.Data.Status)
                return response.Error(httpResponse?.Data?.Message ?? "下发WCS失败");
            stockInfo.StockStatus = (int)StockStatusEmun.出库锁定;
            locationInfo.LocationStatus = (int)LocationStatusEnum.InStockLock;
            _unitOfWorkManage.BeginTran();
            var addTaskResult = await BaseDal.AddDataAsync(task) > 0;
            var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(locationInfo);
            var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
            if (!addTaskResult || !updateLocationResult || !updateStockResult)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("出库任务创建失败");
            }
            _unitOfWorkManage.CommitTran();
            return null;
        }
        private async Task<WebResponseContent> CompleteLocalOutboundAfterAgvAckAsync(Dt_Task task)
        {
            task.TaskStatus = (int)TaskOutStatusEnum.Line_OutFinish;
            _unitOfWorkManage.BeginTran();
            var updateResult = BaseDal.UpdateData(task);
            if (!updateResult)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error("AGV完成回传后,任务更新失败");
            }
            _unitOfWorkManage.CommitTran();
            return WebResponseContent.Instance.OK();
        }
        private bool CanApplyEnter(Dt_Task task, ApplyEnterDto dto)
        {
            if (dto.InOut == 1)
            {
                var hasExecutingOutTask = BaseDal.QueryFirst(x => x.TaskType == (int)TaskOutboundTypeEnum.Outbound
                    && x.TargetAddress == task.SourceAddress
                    && (x.TaskStatus == (int)TaskOutStatusEnum.SC_OutExecuting
                        || x.TaskStatus == (int)TaskOutStatusEnum.Line_OutExecuting));
                // 如果没有正在执行的出库任务,则允许入库
                return hasExecutingOutTask == null;
            }
            else
            {
                return task.TaskType == (int)TaskOutboundTypeEnum.Outbound
                    && task.TaskStatus == (int)TaskStatusEnum.Line_Finish;
            }
        }
        // WCS入库完成
        private async Task<WebResponseContent> CompleteAgvInboundTaskAsync(CreateTaskDto taskDto)
        {
            WebResponseContent response = new WebResponseContent();
            var task = await BaseDal.QueryFirstAsync(x => x.PalletType == taskDto.PalletType);
            if (task == null)
                return response.Error($"没有当前托盘{taskDto.PalletType}入库任务");
            var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
            if (stockInfo == null)
                return response.Error($"未找到托盘{task.PalletCode}的库存信息");
            var locationInfo = await _locationInfoService.GetLocationInfoAsync(task.TargetAddress);
            if (locationInfo == null)
                return response.Error($"未找到货位{task.TargetAddress}的信息");
            if (locationInfo.LocationStatus == (int)LocationStatusEnum.InStock)
                return response.Error($"当前货位{locationInfo.LocationStatus}状态不是空闲状态,无法入库");
            // 更新货位状态为占用
            locationInfo.LocationStatus = (int)LocationStatusEnum.InStock;
            task.TaskStatus = (int)TaskInStatusEnum.InFinish;
            stockInfo.StockStatus = (int)StockStatusEmun.入库完成;
            _unitOfWorkManage.BeginTran();
            var addStockResult = _stockInfoService.UpdateData(stockInfo);
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            if (!addStockResult.Status || !updateLocationResult.Status)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("入库完成后,添加库存或货位更新失败");
            }
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
        // AGV出库完成
        private async Task<AGVResponse> CompleteAgvOutboundTaskAsync(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
            if (stockInfo == null)
                return response.Error($"未找到托盘{task.PalletCode}的库存信息");
            var locationInfo = await _locationInfoService.GetLocationInfoAsync(stockInfo.LocationCode);
            if (locationInfo == null)
                return response.Error($"未找到托盘{stockInfo.LocationCode}的货位信息");
            if (stockInfo.StockStatus != (int)StockStatusEmun.出库锁定 || locationInfo.LocationStatus != (int)LocationStatusEnum.InStockLock)
                return response.Error($"当前库存{stockInfo.StockStatus}或者货位{locationInfo.LocationStatus}状态信息错误");
            locationInfo.LocationStatus = (int)LocationStatusEnum.Free;
            task.TaskStatus = (int)TaskOutStatusEnum.OutFinish;
            _unitOfWorkManage.BeginTran();
            //var deleteStockResult = _stockInfoService.DeleteData(stockInfo)
            var deleteStockResult = await _stockInfoService.DeleteStockWithDetailsAsync(stockInfo.Id);
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            if (!deleteStockResult.Status || !updateLocationResult.Status)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("出库完成后,本地库存或货位更新失败");
            }
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
        // AGV已放货,准备输送线入库
        private async Task<AGVResponse> CompleteAgvInboundTaskAsync(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            var availableLocation = await _locationInfoService.GetLocationInfo(task.Roadway);
            if (availableLocation == null)
                return response.Error("无可用的入库货位");
            task.TargetAddress = availableLocation.LocationCode;
            var wmsTaskDto = _mapper.Map<WMSTaskDTO>(task);
            var taskList = new List<WMSTaskDTO> { wmsTaskDto };
            var requestBody = JsonSerializer.Serialize(taskList);
            var httpResponse = _httpClientHelper.Post<WebResponseContent>(WCS_ReceiveTask, requestBody);
            if (httpResponse == null || httpResponse.Data == null || !httpResponse.Data.Status)
                return response.Error(httpResponse?.Data?.Message ?? "下发WCS失败");
            task.TaskStatus = (int)TaskInStatusEnum.Line_InExecuting;
            task.Dispatchertime = DateTime.Now;
            var locationInfo = await _locationInfoService.GetLocationInfoAsync(task.TargetAddress);
            if (locationInfo == null)
                return response.Error($"未找到托盘{task.TargetAddress}的货位信息");
            if (locationInfo.LocationStatus != (int)LocationStatusEnum.Free)
                return response.Error($"当前货位{locationInfo.LocationStatus}状态信息错误");
            var existingStock = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
            if (existingStock != null)
                return response.Error($"托盘{task.PalletCode}的库存信息已存在,请勿重复入库");
            //Dt_StockInfo stockInfo = new Dt_StockInfo
            //{
            //    PalletCode = task.PalletCode,
            //    StockStatus = (int)StockStatusEmun.入库确认,
            //    LocationCode = locationInfo.LocationCode,
            //    WarehouseId = task.WarehouseId,
            //    Creater = "AGV",
            //    CreateDate = DateTime.Now
            //};
            locationInfo.LocationStatus = (int)LocationStatusEnum.FreeLock;
            _unitOfWorkManage.BeginTran();
            var updateTaskResult = BaseDal.UpdateData(task);
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            //var addStockResult = _stockInfoService.AddData(stockInfo);
            if (!updateTaskResult || !updateLocationResult.Status /*|| !addStockResult.Status*/)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("入库完成后,本地任务、库存或货位更新失败");
            }
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
        // AGV入库取消
        private async Task<AGVResponse> CancelAgvInboundTask(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            task.TaskStatus = (int)TaskInStatusEnum.InCancel;
            _unitOfWorkManage.BeginTran();
            try
            {
                var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
                if (stockInfo != null)
                {
                    var deleteResult = await _stockInfoService.DeleteStockWithDetailsAsync(stockInfo.Id);
                    if (!deleteResult.Status)
                    {
                        _unitOfWorkManage.RollbackTran();
                        return response.Error($"删除库存失败: {deleteResult.Message}");
                    }
                }
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _unitOfWorkManage.CommitTran();
                return response.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"取消入库任务时发生异常: {ex.Message}");
            }
        }
        // AGV出库取消
        private async Task<AGVResponse> CancelAgvOutboundTaskAsync(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
            if (stockInfo == null)
                return response.Error($"未找到托盘{task.PalletCode}的库存信息");
            var locationInfo = await _locationInfoService.GetLocationInfoAsync(stockInfo.LocationCode);
            if (locationInfo == null)
                return response.Error($"未找到托盘{stockInfo.LocationCode}的货位信息");
            if (stockInfo.StockStatus != (int)StockStatusEmun.出库锁定 || locationInfo.LocationStatus != (int)LocationStatusEnum.InStockLock)
                return response.Error($"当前库存{stockInfo.StockStatus}或者货位{locationInfo.LocationStatus}状态信息错误");
            stockInfo.StockStatus = (int)StockStatusEmun.入库完成;
            locationInfo.LocationStatus = (int)LocationStatusEnum.InStock;
            task.TaskStatus = (int)TaskOutStatusEnum.OutCancel;
            _unitOfWorkManage.BeginTran();
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            var updateStockResult = _stockInfoService.UpdateData(stockInfo);
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            if (!updateLocationResult.Status || !updateStockResult.Status)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("出库任务取消失败");
            }
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
        #endregion 具体实现
    }
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"入库任务创建异常:{ex.Message}");
            }
        }
        // 出库创建
        private async Task<AGVResponse?> CreateAgvOutboundTaskAsync(Dt_Task task, ApplyInOutDto dto)
        {
            AGVResponse response = new AGVResponse();
            // 检查库存是否存在
            var stockInfo = await _stockInfoService.GetStockInfoAsync(dto.TrayNumber);
            if (stockInfo == null)
                return response.Error($"未找到托盘{dto.TrayNumber}的库存信息");
            // 检查库存是否有明细(即是否真的有库存)
            if (stockInfo.Details == null || !stockInfo.Details.Any())
                return response.Error($"托盘{dto.TrayNumber}没有库存明细,无法出库");
            // 检查库存总数量是否大于0
            var totalQuantity = stockInfo.Details.Sum(d => d.StockQuantity);
            if (totalQuantity <= 0)
                return response.Error($"托盘{dto.TrayNumber}库存数量不足,无法出库");
            // 根据dto参数进一步验证库存信息
            if (!string.IsNullOrEmpty(dto.ProductNo))
            {
                // 检查库存明细中是否包含指定的物料编码
                var hasMatchingMaterial = stockInfo.Details.Any(d => d.MaterielCode == dto.ProductNo);
                if (!hasMatchingMaterial)
                    return response.Error($"托盘{dto.TrayNumber}中没有物料编码为{dto.ProductNo}的库存,无法出库");
            }
            // 检查库存状态是否允许出库
            if (stockInfo.StockStatus != (int)StockStatusEmun.入库完成)
                return response.Error($"托盘{dto.TrayNumber}正在移动中,请稍后!");
            // 检查货位信息
            var locationInfo = await _locationInfoService.GetLocationInfo(stockInfo.LocationCode);
            if (locationInfo == null)
                return response.Error($"未找到托盘{stockInfo.LocationCode}的货位信息");
            // 检查货位状态是否允许出库
            if (locationInfo.LocationStatus != (int)LocationStatusEnum.InStock)
                return response.Error($"当前货位{locationInfo.LocationStatus}状态信息错误");
            // 验证仓库ID是否匹配(根据dto的阴阳极参数)
            var expectedWarehouseId = dto.YinYang == 1 ? (int)WarehouseEnum.FJ1 : (int)WarehouseEnum.ZJ1;
            if (stockInfo.WarehouseId != expectedWarehouseId)
                return response.Error($"托盘{dto.TrayNumber}不在预期的仓库中,无法出库");
            task.TaskType = (int)TaskOutboundTypeEnum.Outbound;
            task.TaskStatus = (int)TaskOutStatusEnum.OutNew;
            task.SourceAddress = stockInfo.LocationCode;
            task.CurrentAddress = stockInfo.LocationCode;
            task.TargetAddress = dto.YinYang == 1 ? "D10020" : "D10090";
            var wmsTaskDto = _mapper.Map<WMSTaskDTO>(task);
            var taskList = new List<WMSTaskDTO> { wmsTaskDto };
            var requestBody = JsonSerializer.Serialize(taskList);
            var httpResponse = _httpClientHelper.Post<WebResponseContent>(WCS_ReceiveTask, requestBody);
            if (httpResponse == null || httpResponse.Data == null || !httpResponse.Data.Status)
                return response.Error(httpResponse?.Data?.Message ?? "下发WCS失败");
            stockInfo.StockStatus = (int)StockStatusEmun.出库锁定;
            locationInfo.LocationStatus = (int)LocationStatusEnum.InStockLock;
            _unitOfWorkManage.BeginTran();
            var addTaskResult = await BaseDal.AddDataAsync(task) > 0;
            var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(locationInfo);
            var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
            if (!addTaskResult || !updateLocationResult || !updateStockResult)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("出库任务创建失败");
            }
            _unitOfWorkManage.CommitTran();
            return null;
        }
        private async Task<WebResponseContent> CompleteLocalOutboundAfterAgvAckAsync(Dt_Task task)
        {
            task.TaskStatus = (int)TaskOutStatusEnum.Line_OutFinish;
            _unitOfWorkManage.BeginTran();
            var updateResult = BaseDal.UpdateData(task);
            if (!updateResult)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error("AGV完成回传后,任务更新失败");
            }
            _unitOfWorkManage.CommitTran();
            return WebResponseContent.Instance.OK();
        }
        private bool CanApplyEnter(Dt_Task task, ApplyEnterDto dto)
        {
            if (dto.InOut == 1)
            {
                var hasExecutingOutTask = BaseDal.QueryFirst(x => x.TaskType == (int)TaskOutboundTypeEnum.Outbound
                    && x.TargetAddress == task.SourceAddress
                    && (x.TaskStatus == (int)TaskOutStatusEnum.SC_OutExecuting
                        || x.TaskStatus == (int)TaskOutStatusEnum.Line_OutExecuting));
                // 如果没有正在执行的出库任务,则允许入库
                return hasExecutingOutTask == null;
            }
            else
            {
                return task.TaskType == (int)TaskOutboundTypeEnum.Outbound
                    && task.TaskStatus == (int)TaskStatusEnum.Line_Finish;
            }
        }
        // WCS入库完成
        private async Task<WebResponseContent> CompleteAgvInboundTaskAsync(CreateTaskDto taskDto)
        {
            WebResponseContent response = new WebResponseContent();
            var task = await BaseDal.QueryFirstAsync(x => x.PalletType == taskDto.PalletType);
            if (task == null)
                return response.Error($"没有当前托盘{taskDto.PalletType}入库任务");
            var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
            if (stockInfo == null)
                return response.Error($"未找到托盘{task.PalletCode}的库存信息");
            var locationInfo = await _locationInfoService.GetLocationInfoAsync(task.TargetAddress);
            if (locationInfo == null)
                return response.Error($"未找到货位{task.TargetAddress}的信息");
            if (locationInfo.LocationStatus == (int)LocationStatusEnum.InStock)
                return response.Error($"当前货位{locationInfo.LocationStatus}状态不是空闲状态,无法入库");
            // 更新货位状态为占用
            locationInfo.LocationStatus = (int)LocationStatusEnum.InStock;
            task.TaskStatus = (int)TaskInStatusEnum.InFinish;
            stockInfo.StockStatus = (int)StockStatusEmun.入库完成;
            _unitOfWorkManage.BeginTran();
            var addStockResult = _stockInfoService.UpdateData(stockInfo);
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            if (!addStockResult.Status || !updateLocationResult.Status)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("入库完成后,添加库存或货位更新失败");
            }
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
        // AGV出库完成
        private async Task<AGVResponse> CompleteAgvOutboundTaskAsync(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
            if (stockInfo == null)
                return response.Error($"未找到托盘{task.PalletCode}的库存信息");
            var locationInfo = await _locationInfoService.GetLocationInfoAsync(stockInfo.LocationCode);
            if (locationInfo == null)
                return response.Error($"未找到托盘{stockInfo.LocationCode}的货位信息");
            if (stockInfo.StockStatus != (int)StockStatusEmun.出库锁定 || locationInfo.LocationStatus != (int)LocationStatusEnum.InStockLock)
                return response.Error($"当前库存{stockInfo.StockStatus}或者货位{locationInfo.LocationStatus}状态信息错误");
            locationInfo.LocationStatus = (int)LocationStatusEnum.Free;
            task.TaskStatus = (int)TaskOutStatusEnum.OutFinish;
            _unitOfWorkManage.BeginTran();
            //var deleteStockResult = _stockInfoService.DeleteData(stockInfo)
            var deleteStockResult = await _stockInfoService.DeleteStockWithDetailsAsync(stockInfo.Id);
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            if (!deleteStockResult.Status || !updateLocationResult.Status)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("出库完成后,本地库存或货位更新失败");
            }
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
        // AGV已放货,准备输送线入库
        private async Task<AGVResponse> CompleteAgvInboundTaskAsync(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            var availableLocation = await _locationInfoService.GetLocationInfo(task.Roadway);
            if (availableLocation == null)
                return response.Error("无可用的入库货位");
            task.TargetAddress = availableLocation.LocationCode;
            var wmsTaskDto = _mapper.Map<WMSTaskDTO>(task);
            var taskList = new List<WMSTaskDTO> { wmsTaskDto };
            var requestBody = JsonSerializer.Serialize(taskList);
            var httpResponse = _httpClientHelper.Post<WebResponseContent>(WCS_ReceiveTask, requestBody);
            if (httpResponse == null || httpResponse.Data == null || !httpResponse.Data.Status)
                return response.Error(httpResponse?.Data?.Message ?? "下发WCS失败");
            task.TaskStatus = (int)TaskInStatusEnum.Line_InExecuting;
            task.Dispatchertime = DateTime.Now;
            var locationInfo = await _locationInfoService.GetLocationInfoAsync(task.TargetAddress);
            if (locationInfo == null)
                return response.Error($"未找到托盘{task.TargetAddress}的货位信息");
            if (locationInfo.LocationStatus != (int)LocationStatusEnum.Free)
                return response.Error($"当前货位{locationInfo.LocationStatus}状态信息错误");
            var existingStock = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
            if (existingStock != null)
                return response.Error($"托盘{task.PalletCode}的库存信息已存在,请勿重复入库");
            //Dt_StockInfo stockInfo = new Dt_StockInfo
            //{
            //    PalletCode = task.PalletCode,
            //    StockStatus = (int)StockStatusEmun.入库确认,
            //    LocationCode = locationInfo.LocationCode,
            //    WarehouseId = task.WarehouseId,
            //    Creater = "AGV",
            //    CreateDate = DateTime.Now
            //};
            locationInfo.LocationStatus = (int)LocationStatusEnum.FreeLock;
            _unitOfWorkManage.BeginTran();
            var updateTaskResult = BaseDal.UpdateData(task);
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            //var addStockResult = _stockInfoService.AddData(stockInfo);
            if (!updateTaskResult || !updateLocationResult.Status /*|| !addStockResult.Status*/)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("入库完成后,本地任务、库存或货位更新失败");
            }
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
        // AGV入库取消
        private async Task<AGVResponse> CancelAgvInboundTask(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            task.TaskStatus = (int)TaskInStatusEnum.InCancel;
            _unitOfWorkManage.BeginTran();
            try
            {
                var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
                if (stockInfo != null)
                {
                    var deleteResult = await _stockInfoService.DeleteStockWithDetailsAsync(stockInfo.Id);
                    if (!deleteResult.Status)
                    {
                        _unitOfWorkManage.RollbackTran();
                        return response.Error($"删除库存失败: {deleteResult.Message}");
                    }
                }
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _unitOfWorkManage.CommitTran();
                return response.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"取消入库任务时发生异常: {ex.Message}");
            }
        }
        // AGV出库取消
        private async Task<AGVResponse> CancelAgvOutboundTaskAsync(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
            if (stockInfo == null)
                return response.Error($"未找到托盘{task.PalletCode}的库存信息");
            var locationInfo = await _locationInfoService.GetLocationInfoAsync(stockInfo.LocationCode);
            if (locationInfo == null)
                return response.Error($"未找到托盘{stockInfo.LocationCode}的货位信息");
            if (stockInfo.StockStatus != (int)StockStatusEmun.出库锁定 || locationInfo.LocationStatus != (int)LocationStatusEnum.InStockLock)
                return response.Error($"当前库存{stockInfo.StockStatus}或者货位{locationInfo.LocationStatus}状态信息错误");
            stockInfo.StockStatus = (int)StockStatusEmun.入库完成;
            locationInfo.LocationStatus = (int)LocationStatusEnum.InStock;
            task.TaskStatus = (int)TaskOutStatusEnum.OutCancel;
            _unitOfWorkManage.BeginTran();
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            var updateStockResult = _stockInfoService.UpdateData(stockInfo);
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            if (!updateLocationResult.Status || !updateStockResult.Status)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("出库任务取消失败");
            }
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
        #endregion 具体实现
    }
}