using Microsoft.Extensions.Logging; using Newtonsoft.Json; using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEA_Common.CommonEnum; using WIDESEA_Common.LocationEnum; using WIDESEA_Common.OrderEnum; using WIDESEA_Common.OtherEnum; using WIDESEA_Common.StockEnum; using WIDESEA_Common.TaskEnum; using WIDESEA_Core; using WIDESEA_Core.Helper; using WIDESEA_DTO.Basic; using WIDESEA_DTO.Stock; using WIDESEA_Model.Models; namespace WIDESEA_TaskInfoService { public partial class TaskService { /// /// 空托盘出库任务 /// /// /// public async Task PalletOutboundTask(string endStation, string palletCode = "") { try { Dt_StockInfo stockInfo; if (string.IsNullOrEmpty(palletCode)) { stockInfo = _stockRepository.Db.Queryable().Where(x => x.PalletType == PalletTypeEnum.Empty.ObjToInt() && x.StockStatus == StockStatusEmun.入库完成.ObjToInt() && !string.IsNullOrWhiteSpace(x.LocationCode)).First(); } else { stockInfo = _stockRepository.Db.Queryable().Where(x => x.PalletType == PalletTypeEnum.Empty.ObjToInt() && x.PalletCode == palletCode && x.StockStatus == StockStatusEmun.入库完成.ObjToInt()).First(); } if (stockInfo == null) { return WebResponseContent.Instance.Error("未找到空托盘库存"); } Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == stockInfo.LocationCode); if (locationInfo == null) { return WebResponseContent.Instance.Error("未找到空托盘库存对应的货位信息"); } Dt_Task task = new Dt_Task() { CurrentAddress = stockInfo.LocationCode, Grade = 0, NextAddress = endStation, PalletCode = stockInfo.PalletCode, Roadway = locationInfo.RoadwayNo, SourceAddress = stockInfo.LocationCode, TargetAddress = endStation, TaskStatus = TaskStatusEnum.New.ObjToInt(), TaskType = TaskTypeEnum.OutEmpty.ObjToInt(), WarehouseId = stockInfo.WarehouseId, PalletType = stockInfo.PalletType }; int beforeStatus = locationInfo.LocationStatus; _unitOfWorkManage.BeginTran(); stockInfo.StockStatus = StockStatusEmun.出库锁定.ObjToInt(); locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt(); int taskId = BaseDal.AddData(task); task.TaskId = taskId; _stockService.StockInfoService.UpdateData(stockInfo); _locationInfoService.UpdateData(locationInfo); _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), "", task.TaskNum); _unitOfWorkManage.CommitTran(); TaskModel esstask = new TaskModel() { taskType = "carry", taskGroupCode = "", groupPriority = 0, tasks = new List { new() { taskCode=task.TaskNum.ToString(), taskPriority=0, taskDescribe=new TaskDescribeType{ containerCode=stockInfo.PalletCode, containerType= "CT_KUBOT_STANDARD", fromLocationCode=stockInfo.LocationCode??"", toStationCode="", toLocationCode=endStation, deadline=0,storageTag="" } } } }; var result = await _eSSApiService.CreateTaskAsync(esstask); _logger.LogInformation("创建任务PalletOutboundTask 返回: " + result); if (result) { return WebResponseContent.Instance.OK(200); } else { return WebResponseContent.Instance.Error("下发机器人任务失败!"); } } catch (Exception ex) { return WebResponseContent.Instance.Error(ex.Message); } } /// /// 出库任务数据处理 /// /// /// /// /// public (List, List?, List?, List?, List?) OutboundTaskDataHandle(int[] keys, string outStation) { List tasks = new List(); List outboundOrderDetails = _outboundOrderDetailService.Repository.QueryData(x => keys.Contains(x.Id)); if (outboundOrderDetails == null || outboundOrderDetails.Count == 0) { throw new Exception("未找到出库单明细信息"); } if (outboundOrderDetails.FirstOrDefault(x => x.OrderDetailStatus > OrderDetailStatusEnum.New.ObjToInt() && x.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) != null) { throw new Exception("所选出库单明细存在出库中或已完成"); } List? stockInfos = null; List? orderDetails = null; List? outStockLockInfos = null; List? locationInfos = null; (List, List, List, List) result = _outboundOrderDetailService.AssignStockOutbound(outboundOrderDetails); if (result.Item1 != null && result.Item1.Count > 0) { Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId); TaskTypeEnum typeEnum = outboundOrder.OrderType switch { (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound, (int)OutOrderTypeEnum.Allocate => TaskTypeEnum.OutAllocate, (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality, _ => TaskTypeEnum.Outbound }; tasks = GetTasks(result.Item1, typeEnum, outStation); tasks.ForEach(x => { x.OrderNo = outboundOrder.OrderNo; }); result.Item2.ForEach(x => { x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); }); result.Item3.ForEach(x => { x.Status = OutLockStockStatusEnum.出库中.ObjToInt(); }); stockInfos = result.Item1; orderDetails = result.Item2; outStockLockInfos = result.Item3; locationInfos = result.Item4; } else { throw new Exception("无库存"); } return (tasks, stockInfos, orderDetails, outStockLockInfos, locationInfos); } /// /// 生成出库任务后数据更新到数据库 /// /// /// /// /// /// /// public async Task GenerateOutboundTaskDataUpdateAsync(List tasks, List? stockInfos = null, List? outboundOrderDetails = null, List? outStockLockInfos = null, List? locationInfos = null) { try { _unitOfWorkManage.BeginTran(); BaseDal.AddData(tasks); if (stockInfos != null && stockInfos.Count > 0 && outboundOrderDetails != null && outboundOrderDetails.Count > 0 && outStockLockInfos != null && outStockLockInfos.Count > 0 && locationInfos != null && locationInfos.Count > 0) { stockInfos.ForEach(x => { x.StockStatus = StockStatusEmun.出库锁定.ObjToInt(); }); outboundOrderDetails.ForEach(x => { x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); }); Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId); if (outboundOrder.OrderStatus != OutOrderStatusEnum.出库中.ObjToInt()) { _outboundOrderService.Repository.UpdateData(outboundOrder); } else { outboundOrder.OrderStatus = OutOrderStatusEnum.出库中.ObjToInt(); } outboundOrder.Operator = App.User.UserName; _outboundOrderService.Repository.UpdateData(outboundOrder); WebResponseContent content = _outboundOrderDetailService.LockOutboundStockDataUpdate(stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos, tasks: tasks); if (!content.Status) { _unitOfWorkManage.RollbackTran(); return content; } } else if (outboundOrderDetails != null && outboundOrderDetails.Count > 0) { outboundOrderDetails.ForEach(x => { x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); }); Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId); if (outboundOrder.OrderStatus != OutOrderStatusEnum.出库中.ObjToInt()) { _outboundOrderService.Repository.UpdateData(outboundOrder); } else { outboundOrder.OrderStatus = OutOrderStatusEnum.出库中.ObjToInt(); } outboundOrder.Operator = App.User.UserName; _outboundOrderService.Repository.UpdateData(outboundOrder); _outboundOrderDetailService.Repository.UpdateData(outboundOrderDetails); } _unitOfWorkManage.CommitTran(); TaskModel esstask = new TaskModel() { taskType = "carry", taskGroupCode = "", groupPriority = 0, tasks = new List() }; foreach (var task in tasks) { esstask. tasks.Add(new TasksType { taskCode = task.TaskNum.ToString(), taskPriority = 0, taskDescribe = new TaskDescribeType { containerCode = task.PalletCode, containerType = "CT_KUBOT_STANDARD", fromLocationCode = task.SourceAddress ?? "", toStationCode = "", toLocationCode = task.TargetAddress, deadline = 0, storageTag = "" } } ); } var result = await _eSSApiService.CreateTaskAsync(esstask); _logger.LogInformation("创建任务PalletOutboundTask 返回: " + result); if (result) { return WebResponseContent.Instance.OK(); } else { return WebResponseContent.Instance.Error("下发机器人任务失败!"); } } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } /// /// 库存数据转出库任务 /// /// /// public List GetTasks(List stockInfos, TaskTypeEnum taskType, string outStation) { List tasks = new List(); List locationInfos = _locationInfoService.Repository.QueryData(x => stockInfos.Select(x => x.LocationCode).Contains(x.LocationCode)); for (int i = 0; i < stockInfos.Count; i++) { Dt_StockInfo stockInfo = stockInfos[i]; if (stockInfo != null) { Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x => x.LocationCode == stockInfo.LocationCode); if (!tasks.Exists(x => x.PalletCode == stockInfo.PalletCode)) { Dt_Task task = new() { CurrentAddress = stockInfo.LocationCode, Grade = 0, PalletCode = stockInfo.PalletCode, NextAddress = "", Roadway = locationInfo.RoadwayNo, SourceAddress = stockInfo.LocationCode, TargetAddress = outStation, TaskStatus = TaskStatusEnum.New.ObjToInt(), TaskType = taskType.ObjToInt(), // TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)), PalletType = stockInfo.PalletType, WarehouseId = stockInfo.WarehouseId, }; //if (taskType != TaskTypeEnum.OutEmpty) //{ // task.MaterielCode = stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).FirstOrDefault()?.MaterielCode; // task.Quantity = (float)stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).Sum(x => x.StockQuantity); // task.BatchNo = stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).FirstOrDefault()?.BatchNo; //} tasks.Add(task); } } } return tasks; } public List GetTasks(List stockInfos, TaskTypeEnum taskType) { List tasks = new List(); List locationInfos = _locationInfoService.Repository.QueryData(x => stockInfos.Select(x => x.LocationCode).Contains(x.LocationCode)); for (int i = 0; i < stockInfos.Count; i++) { Dt_StockInfo stockInfo = stockInfos[i]; if (stockInfo != null) { Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x => x.LocationCode == stockInfo.LocationCode); if (!tasks.Exists(x => x.PalletCode == stockInfo.PalletCode)) { Dt_Task task = new() { CurrentAddress = stockInfo.LocationCode, Grade = 0, PalletCode = stockInfo.PalletCode, NextAddress = "", Roadway = locationInfo.RoadwayNo, SourceAddress = stockInfo.LocationCode, TargetAddress = "", TaskStatus = TaskStatusEnum.New.ObjToInt(), TaskType = taskType.ObjToInt(), //TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)), PalletType = stockInfo.PalletType, WarehouseId = stockInfo.WarehouseId, }; //if (taskType != TaskTypeEnum.OutEmpty) //{ // task.MaterielCode = stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).FirstOrDefault()?.MaterielCode; // task.Quantity = (float)stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).Sum(x => x.StockQuantity); // task.BatchNo = stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).FirstOrDefault()?.BatchNo; //} //if (stockInfo.StockLength > 0) //{ // task.TaskLength = stockInfo.StockLength; //} tasks.Add(task); } } } return tasks; } /// /// 生成出库任务 /// /// 出库单明细主键 /// public async Task GenerateOutboundTasksAsync(int[] keys, string outStation) { try { List tasks = new List(); List stockSelectViews = new List(); List stockInfos = new List(); List outboundOrderDetails = new List(); List outStockLockInfos = new List(); List locationInfos = new List(); (List, List?, List?, List?, List?) result = OutboundTaskDataHandle(keys, outStation); if (result.Item2 != null && result.Item2.Count > 0) { stockInfos.AddRange(result.Item2); } if (result.Item3 != null && result.Item3.Count > 0) { outboundOrderDetails.AddRange(result.Item3); } if (result.Item4 != null && result.Item4.Count > 0) { outStockLockInfos.AddRange(result.Item4); } if (result.Item5 != null && result.Item5.Count > 0) { locationInfos.AddRange(result.Item5); } if (result.Item1 != null && result.Item1.Count > 0) { tasks.AddRange(result.Item1); } WebResponseContent content = await GenerateOutboundTaskDataUpdateAsync(tasks, stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos); return content; } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } /// /// 生成出库任务 /// /// /// /// public WebResponseContent GenerateOutboundTask(int orderDetailId, List stockSelectViews) { try { (List, List?, List?, List?, List?) result = OutboundTaskDataHandle(orderDetailId, stockSelectViews); WebResponseContent content = GenerateOutboundTaskDataUpdate(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5); return content; } catch (Exception ex) { return WebResponseContent.Instance.Error(ex.Message); } } /// /// 出库任务数据处理 /// /// /// /// /// public (List, List?, List?, List?, List?) OutboundTaskDataHandle(int orderDetailId, List stockSelectViews) { List tasks = new List(); Dt_OutboundOrderDetail outboundOrderDetail = _outboundOrderDetailService.Repository.QueryFirst(x => x.Id == orderDetailId); if (outboundOrderDetail == null) { throw new Exception("未找到出库单明细信息"); } //if (stockSelectViews.Sum(x => x.UseableQuantity) > outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity) //{ // throw new Exception("选择数量超出单据数量"); //} List? stockInfos = null; Dt_OutboundOrderDetail? orderDetail = null; List? outStockLockInfos = null; List? locationInfos = null; if (outboundOrderDetail.OrderDetailStatus == OrderDetailStatusEnum.New.ObjToInt()) { (List, Dt_OutboundOrderDetail, List, List) result = _outboundOrderDetailService.AssignStockOutbound(outboundOrderDetail, stockSelectViews); if (result.Item1 != null && result.Item1.Count > 0) { Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId); TaskTypeEnum typeEnum = outboundOrder.OrderType switch { (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound, (int)OutOrderTypeEnum.Allocate => TaskTypeEnum.OutAllocate, (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality, _ => new TaskTypeEnum() }; tasks = GetTasks(result.Item1, typeEnum); result.Item2.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); result.Item3.ForEach(x => { x.Status = OutLockStockStatusEnum.出库中.ObjToInt(); }); stockInfos = result.Item1; orderDetail = result.Item2; outStockLockInfos = result.Item3; locationInfos = result.Item4; } else { throw new Exception("无库存"); } } else { List stockLockInfos = _outStockLockInfoService.GetByOrderDetailId(outboundOrderDetail.OrderId, OutLockStockStatusEnum.已分配); if (stockLockInfos != null && stockLockInfos.Count > 0) { List stocks = _stockService.StockInfoService.GetStockInfosByPalletCodes(stockLockInfos.Select(x => x.PalletCode).Distinct().ToList()); tasks = GetTasks(stocks, TaskTypeEnum.Outbound); } } return (tasks, stockInfos, orderDetail == null ? null : new List { orderDetail }, outStockLockInfos, locationInfos); } /// /// 生成出库任务后数据更新到数据库 /// /// /// /// /// /// /// public WebResponseContent GenerateOutboundTaskDataUpdate(List tasks, List? stockInfos = null, List? outboundOrderDetails = null, List? outStockLockInfos = null, List? locationInfos = null) { try { _unitOfWorkManage.BeginTran(); BaseDal.AddData(tasks); if (stockInfos != null && stockInfos.Count > 0 && outboundOrderDetails != null && outboundOrderDetails.Count > 0 && outStockLockInfos != null && outStockLockInfos.Count > 0 && locationInfos != null && locationInfos.Count > 0) { stockInfos.ForEach(x => { x.StockStatus = StockStatusEmun.出库锁定.ObjToInt(); }); outboundOrderDetails.ForEach(x => { x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); }); Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId); if (outboundOrder.OrderStatus != OutOrderStatusEnum.出库中.ObjToInt()) { _outboundOrderService.Repository.UpdateData(outboundOrder); } WebResponseContent content = _outboundOrderDetailService.LockOutboundStockDataUpdate(stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos, tasks: tasks); if (!content.Status) { _unitOfWorkManage.RollbackTran(); return content; } } else if (outboundOrderDetails != null && outboundOrderDetails.Count > 0) { outboundOrderDetails.ForEach(x => { x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); }); Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId); if (outboundOrder.OrderStatus != OutOrderStatusEnum.出库中.ObjToInt()) { _outboundOrderService.Repository.UpdateData(outboundOrder); } _outboundOrderDetailService.Repository.UpdateData(outboundOrderDetails); } _unitOfWorkManage.CommitTran(); //PushTasksToWCS(tasks); return WebResponseContent.Instance.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } } }