using Mapster; using MapsterMapper; using Microsoft.Extensions.Configuration; using SqlSugar; using System.DirectoryServices.Protocols; using System.Text.Json; using WIDESEA_Common.LocationEnum; using WIDESEA_Common.StockEnum; using WIDESEA_Common.TaskEnum; using WIDESEA_Common.WareHouseEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_Core.Core; using WIDESEA_Core.Enums; using WIDESEA_Core.Helper; using WIDESEA_DTO.GradingMachine; using WIDESEA_DTO.MES; using WIDESEA_DTO.Stock; using WIDESEA_DTO.Task; using WIDESEA_IBasicService; using WIDESEA_IStockService; using WIDESEA_ITaskInfoService; using WIDESEA_Model.Models; namespace WIDESEA_TaskInfoService { public partial class TaskService { #region 极卷库任务模块 public string AGV_OutTaskComplete = WIDESEA_Core.Helper.AppSettings.Configuration["AGV_OutTaskComplete"]; // 上报AGV出库输送线完成 public string WCS_ReceiveTask = WIDESEA_Core.Helper.AppSettings.Configuration["WCS_ReceiveTask"]; // WMS输送线任务下发 /// /// 出入库申请 /// /// 请求参数 /// public async Task ApplyInOutAsync(ApplyInOutDto applyInOutDto) { AGVResponse aGVResponse = new AGVResponse(); try { // 参数验证 if (applyInOutDto == null) return aGVResponse.Error("请求参数不能为空"); if (string.IsNullOrWhiteSpace(applyInOutDto.TrayNumber)) return aGVResponse.Error("托盘号不能为空"); if (string.IsNullOrWhiteSpace(applyInOutDto.TaskId)) return aGVResponse.Error("任务号不能为空"); if (string.IsNullOrWhiteSpace(applyInOutDto.MaterialType)) return aGVResponse.Error("物料类型不能为空"); if (string.IsNullOrWhiteSpace(applyInOutDto.MaterialName)) return aGVResponse.Error("物料描述不能为空"); if (string.IsNullOrWhiteSpace(applyInOutDto.ReqTime)) return aGVResponse.Error("请求时间不能为空"); if (applyInOutDto.Floor != 1 && applyInOutDto.Floor != 2) return aGVResponse.Error($"楼层段错误,必须为1(模切段)或2(卷绕段),当前值:{applyInOutDto.Floor}"); if (applyInOutDto.YinYang != 1 && applyInOutDto.YinYang != 2) return aGVResponse.Error($"阴阳极错误,必须为1(阴极)或2(阳极),当前值:{applyInOutDto.YinYang}"); if (applyInOutDto.InOut != 1 && applyInOutDto.InOut != 2) return aGVResponse.Error($"出入库类型错误,必须为1(入库)或2(出库),当前值:{applyInOutDto.InOut}"); if (applyInOutDto.InOut == 1) // 入库 { if (applyInOutDto.Width == null || applyInOutDto.Width <= 0) return aGVResponse.Error("入库时宽度不能为空且必须大于0"); if (string.IsNullOrWhiteSpace(applyInOutDto.Group)) return aGVResponse.Error("入库时整托组别不能为空"); } // 检查任务是否已存在 var existingTask = await BaseDal.QueryFirstAsync(x => x.PalletCode == applyInOutDto.TrayNumber); if (existingTask != null) return aGVResponse.Error($"WMS已有当前任务,不可重复下发,任务号:{applyInOutDto.TaskId}"); // 创建任务 Dt_Task task = new Dt_Task { OrderNo = applyInOutDto.TaskId, // 使用AGV的任务号 PalletCode = applyInOutDto.TrayNumber, PalletType = applyInOutDto.Floor, //WarehouseId = applyInOutDto.YinYang, Grade = 1, Creater = "AGV", CreateDate = DateTime.Now, Remark = $"物料类型:{applyInOutDto.MaterialType},物料描述:{applyInOutDto.MaterialName}" }; // 根据阴极/阳极设置巷道和站台 if (applyInOutDto.YinYang == 1) // 阴极 { // 货物到达后分配货物位 task.Roadway = WarehouseEnum.FJ1.ToString(); task.WarehouseId = (int)WarehouseEnum.FJ1; task.SourceAddress = applyInOutDto.InOut == 1 ? "D10010" : "D10020"; // 入库口/出库口 task.NextAddress = "D10080"; // 阴极公共出库口 task.TargetAddress = "阴极卷库"; } else if (applyInOutDto.YinYang == 2) // 阳极 { task.Roadway = WarehouseEnum.ZJ1.ToString(); task.WarehouseId = (int)WarehouseEnum.ZJ1; task.SourceAddress = applyInOutDto.InOut == 1 ? "D10100" : "D10090"; // 入库口/出库口 task.NextAddress = "D10160"; // 阳极公共出库口 task.TargetAddress = "正极卷库"; } // 根据出入库类型设置目标地址 if (applyInOutDto.InOut == 1) // 入库 { var stockInfo = await _stockInfoService.GetStockInfoAsync(applyInOutDto.TrayNumber); if (stockInfo != null) return aGVResponse.Error($"当前托盘{applyInOutDto.TrayNumber}已经入库了"); task.TaskType = (int)TaskInboundTypeEnum.Inbound; task.TaskStatus = (int)TaskInStatusEnum.InNew; task.CurrentAddress = task.SourceAddress; // 当前在入库口 // 保存任务 var result = await BaseDal.AddDataAsync(task); } else // 出库 { // 判断是否移库 task.TaskType = (int)TaskOutboundTypeEnum.Outbound; task.TaskStatus = (int)TaskOutStatusEnum.OutNew; task.CurrentAddress = task.SourceAddress; // 当前在入库口 // 查找库存 var stockInfo = await _stockInfoService.GetStockInfoAsync(applyInOutDto.TrayNumber); if (stockInfo == null) return aGVResponse.Error($"未找到托盘{applyInOutDto.TrayNumber}的库存信息"); // 验证库存所属是否正确 if (stockInfo.WarehouseId != applyInOutDto.YinYang) return aGVResponse.Error($"托盘{applyInOutDto.TrayNumber}不属于当前{(applyInOutDto.YinYang == 1 ? "阴极" : "阳极")}"); if (stockInfo.StockStatus != (int)StockStatusEmun.入库完成) return aGVResponse.Error($"托盘{applyInOutDto.TrayNumber}正在移动中,请稍后!"); task.SourceAddress = stockInfo.LocationCode; // 源地址为货位 task.CurrentAddress = stockInfo.LocationCode; // 当前位置在货位 task.TargetAddress = applyInOutDto.YinYang == 1 ? "D10020" : "D10090"; // 目标地址为出库口 // 保存任务 var result = await BaseDal.AddDataAsync(task); // 判断是否移库 //var transferTask = await _locationInfoService.TransferCheckAsync(result); } // 构建响应数据 AGVDataDto aGVDataDto = new AGVDataDto { DevId = applyInOutDto.InOut == 1 ? task.SourceAddress : task.TargetAddress, TrayNumber = task.PalletCode, Group = applyInOutDto.Group, Width = applyInOutDto.Width ?? 0, LabelNumber = applyInOutDto.LabelNumber, ProductNo = applyInOutDto.ProductNo, ProductName = applyInOutDto.ProductName, Quantity = applyInOutDto.Quantity, UomCode = applyInOutDto.UomCode, ProductType = applyInOutDto.ProductType, Equipment = applyInOutDto.Equipment, ProductionDate = applyInOutDto.ProductionDate, LowerLimitTime = applyInOutDto.LowerLimitTime, WarningTime = applyInOutDto.WarningTime, OverdueTime = applyInOutDto.OverdueTime }; return aGVResponse.OK(aGVDataDto); } catch (Exception ex) { return aGVResponse.Error($"WMS任务创建接口错误: {ex.Message}"); } } /// /// 手动出库完成反馈给AGV /// /// 请求参数 /// public async Task OutTaskComplete(OutTaskCompleteDto outTaskCompleteDto) { WebResponseContent webResponse = new WebResponseContent(); try { if (outTaskCompleteDto == null) return webResponse.Error("请求参数不能为空"); if (string.IsNullOrWhiteSpace(outTaskCompleteDto.TaskId)) return webResponse.Error("任务号不能为空"); if (string.IsNullOrWhiteSpace(outTaskCompleteDto.DevId)) return webResponse.Error("出库口编号不能为空"); var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == outTaskCompleteDto.TaskId); if (task == null) return webResponse.Error("未找到任务信息"); outTaskCompleteDto.ReqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); var httpResponse = _httpClientHelper.Post(AGV_OutTaskComplete, outTaskCompleteDto.ToJson()).Data; // 判断远程接口返回是否成功 if (httpResponse != null && httpResponse.Data != null) { AGVResponse agvResponse = httpResponse; // 根据code字段判断,code为true表示成功 if (agvResponse.Code == true) { var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode); if (stockInfo == null) return webResponse.Error($"未找到托盘{task.PalletCode}的库存信息"); var locationInfo = await _locationInfoService.GetLocationInfoAsync(stockInfo.LocationCode); if (locationInfo == null) return webResponse.Error($"未找到托盘{stockInfo.LocationCode}的货位信息"); if (stockInfo.StockStatus != (int)StockStatusEmun.出库锁定 || locationInfo.LocationStatus != (int)LocationStatusEnum.InStockLock) { return webResponse.Error($"当前库存{stockInfo.StockStatus}或者货位{locationInfo.LocationStatus}状态信息错误"); } locationInfo.LocationStatus = (int)LocationStatusEnum.Free; _unitOfWorkManage.BeginTran(); BaseDal.DeleteData(task); _locationInfoService.UpdateData(locationInfo); _stockInfoService.DeleteData(stockInfo); _unitOfWorkManage.CommitTran(); return webResponse.OK(agvResponse.Msg); } else { // 失败:返回AGV返回的错误信息 return webResponse.Error(string.IsNullOrWhiteSpace(agvResponse.Msg) ? "AGV接口调用失败" : agvResponse.Msg); } } else { // HTTP请求本身失败 return webResponse.Error(httpResponse?.Msg ?? "AGV接口调用异常"); } } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return webResponse.Error($"WMS任务完成接口错误:{ex.Message}"); } } ///// ///// 任务完成接口 ///// ///// ///// //public async Task TaskCompleted(WCSTaskDTO wCSTask) //{ // WebResponseContent webResponse = new WebResponseContent(); // try // { // Dt_Task task = await BaseDal.QueryFirstAsync(x => x.TaskId == wCSTask.TaskNum && x.PalletCode == wCSTask.PalletCode); // if (task == null) return webResponse.Error("未找到任务信息"); // // 出库完成反馈 // OutTaskCompleteDto outTaskCompleteDto = new OutTaskCompleteDto() // { // TaskId = task.OrderNo, // DevId = task.TargetAddress, // ReqTime = DateTime.Now.ToString() // }; // return await OutTaskComplete(outTaskCompleteDto); // } // catch (Exception ex) // { // return webResponse.Error($"WMS任务完成接口错误:{ex.Message}"); // } //} /// /// 输送线申请进入 /// /// 请求参数 /// public async Task ApplyEnterAsync(ApplyEnterDto applyEnterDto) { AGVResponse aGVResponse = new AGVResponse(); try { // 参数验证 if (applyEnterDto == null) return aGVResponse.Error("请求参数不能为空"); if (string.IsNullOrWhiteSpace(applyEnterDto.DevId)) return aGVResponse.Error("设备编号不能为空"); if (string.IsNullOrWhiteSpace(applyEnterDto.TaskId)) return aGVResponse.Error("任务号不能为空"); if (applyEnterDto.InOut != 1 && applyEnterDto.InOut != 2) return aGVResponse.Error($"出入库类型错误,必须为1(入库)或2(出库),当前值:{applyEnterDto.InOut}"); // 查询任务是否存在 var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == applyEnterDto.TaskId); if (task == null) return aGVResponse.Error($"未找到任务信息,任务号:{applyEnterDto.TaskId}"); if (applyEnterDto.InOut == 1 && task.TaskType == (int)TaskInboundTypeEnum.Inbound && task.TaskStatus == (int)TaskInStatusEnum.InNew) { aGVResponse.OK(); } else if (applyEnterDto.InOut == 2 && task.TaskType == (int)TaskOutboundTypeEnum.Outbound && task.TaskStatus == (int)TaskStatusEnum.Line_Finish) { aGVResponse.OK(); } return aGVResponse.Error($"输送线{applyEnterDto.DevId}当前繁忙,请稍后重试"); // Dt_Task.SourceAddress询问wcs站台1-阴极入口叫D10010和D10020;2-阳极D10090和D10100是否有货物 //var httpResponse = _httpClientHelper.Post("http://127.0.0.1:9999/api/Task/ApplyInOut", JsonSerializer.Serialize(task)).Data; //if (httpResponse != null && httpResponse.Status == true) //{ // _unitOfWorkManage.BeginTran(); // task.TaskStatus = (int)TaskStatusEnum.AGV_Executing; // await BaseDal.UpdateDataAsync(task); // _unitOfWorkManage.CommitTran(); // return aGVResponse.OK(); //} //else //{ // return aGVResponse.Error($"站台{task.SourceAddress}已经载货"); //} } catch (Exception ex) { //_unitOfWorkManage.RollbackTran(); return aGVResponse.Error($"WMS输送线申请接口错误:{ex.Message}"); } } /// /// 取放货完成 /// /// 请求参数 /// public async Task TaskCompleteAsync(TaskCompleteDto taskCompleteDto) { AGVResponse aGVResponse = new AGVResponse(); try { if (taskCompleteDto == null) return aGVResponse.Error("请求参数不能为空"); if (string.IsNullOrWhiteSpace(taskCompleteDto.TaskId)) return aGVResponse.Error("任务号不能为空"); if (string.IsNullOrWhiteSpace(taskCompleteDto.DevId)) return aGVResponse.Error("设备编号不能为空"); if (taskCompleteDto.InOut != 1 && taskCompleteDto.InOut != 2) return aGVResponse.Error($"出入库类型错误,必须为1(入库)或2(出库),当前值:{taskCompleteDto.InOut}"); var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == taskCompleteDto.TaskId); if (task == null) return aGVResponse.Error($"未找到任务信息,任务号:{taskCompleteDto.TaskId}"); if (taskCompleteDto.InOut == 2) { var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode); if (stockInfo == null) return aGVResponse.Error($"未找到托盘{task.PalletCode}的库存信息"); var locationInfo = await _locationInfoService.GetLocationInfoAsync(stockInfo.LocationCode); if (locationInfo == null) return aGVResponse.Error($"未找到托盘{stockInfo.LocationCode}的货位信息"); if (stockInfo.StockStatus != (int)StockStatusEmun.出库锁定 || locationInfo.LocationStatus != (int)LocationStatusEnum.InStockLock) { return aGVResponse.Error($"当前库存{stockInfo.StockStatus}或者货位{locationInfo.LocationStatus}状态信息错误"); } locationInfo.LocationStatus = (int)LocationStatusEnum.Free; task.TaskStatus = (int)TaskOutStatusEnum.OutFinish; _unitOfWorkManage.BeginTran(); _stockInfoService.DeleteData(stockInfo); await _locationInfoService.UpdateLocationInfoAsync(locationInfo); BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); _unitOfWorkManage.CommitTran(); } else { //查找可用货位 var availableLocation = await _locationInfoService.GetLocationInfo(task.Roadway); if (availableLocation == null) return aGVResponse.Error("无可用的入库货位"); task.TargetAddress = availableLocation.LocationCode; // 通知WCS入库 var wcsTaskDto = _mapper.Map(task); var httpResponse = _httpClientHelper.Post(WCS_ReceiveTask, JsonSerializer.Serialize(wcsTaskDto)); if (httpResponse == null) return aGVResponse.Error("下发WCS失败"); task.TaskStatus = (int)TaskStatusEnum.Line_Executing; task.Dispatchertime = DateTime.Now; var locationInfo = await _locationInfoService.GetLocationInfoAsync(task.TargetAddress); if (locationInfo == null) return aGVResponse.Error($"未找到托盘{task.TargetAddress}的货位信息"); if (locationInfo.LocationStatus != (int)LocationStatusEnum.InStock) { return aGVResponse.Error($"当前货位{locationInfo.LocationStatus}状态信息错误"); } Dt_StockInfo dt_Stock = 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(); BaseDal.UpdateData(task); _locationInfoService.UpdateData(locationInfo); _stockInfoService.AddData(dt_Stock); _unitOfWorkManage.CommitTran(); } return aGVResponse.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return aGVResponse.Error($"WMS取放货完成接口错误:{ex.Message}"); } } /// /// 任务取消 /// /// 请求参数 /// public async Task TaskCancelAsync(TaskCancelDto taskCancelDto) { AGVResponse aGVResponse = new AGVResponse(); try { if (taskCancelDto == null) return aGVResponse.Error("请求参数不能为空"); if (string.IsNullOrWhiteSpace(taskCancelDto.TaskId)) return aGVResponse.Error("任务号不能为空"); var task = await BaseDal.QueryFirstAsync(x => x.OrderNo == taskCancelDto.TaskId); // 没有任务强制取消 if (task == null) return aGVResponse.OK(); if (task.TaskStatus == (int)TaskInStatusEnum.InNew) { task.TaskStatus = (int)TaskInStatusEnum.InCancel; // 入库任务直接删除 _unitOfWorkManage.BeginTran(); BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); _unitOfWorkManage.CommitTran(); return aGVResponse.OK(); } else if (task.TaskStatus == (int)TaskOutStatusEnum.OutNew) { // 出库任务恢复库存 var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode); if (stockInfo == null) return aGVResponse.Error($"未找到托盘{task.PalletCode}的库存信息"); var locationInfo = await _locationInfoService.GetLocationInfoAsync(stockInfo.LocationCode); if (locationInfo == null) return aGVResponse.Error($"未找到托盘{stockInfo.LocationCode}的货位信息"); if (stockInfo.StockStatus != (int)StockStatusEmun.出库锁定 || locationInfo.LocationStatus != (int)LocationStatusEnum.InStockLock) { return aGVResponse.Error($"当前库存{stockInfo.StockStatus}或者货位{locationInfo.LocationStatus}状态信息错误"); } stockInfo.StockStatus = (int)StockStatusEmun.入库完成; locationInfo.LocationStatus = (int)LocationStatusEnum.InStock; task.TaskStatus = (int)TaskOutStatusEnum.OutCancel; _unitOfWorkManage.BeginTran(); _locationInfoService.UpdateData(locationInfo); _stockInfoService.UpdateData(stockInfo); BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成); _unitOfWorkManage.CommitTran(); return aGVResponse.OK(); } return aGVResponse.Error("任务已经在执行中,不可取消"); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return aGVResponse.Error($"WMS任务取消接口错误:{ex.Message}"); } } #endregion 极卷库任务模块 } }