#region << 版 本 注 释 >>
/*----------------------------------------------------------------
* 命名空间:WIDESEAWCS_TaskInfoService
* 创建者:胡童庆
* 创建时间:2024/8/2 16:13:36
* 版本:V1.0.0
* 描述:
*
* ----------------------------------------------------------------
* 修改人:
* 修改时间:
* 版本:V1.0.1
* 修改说明:
*
*----------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using HslCommunication;
using HslCommunication.WebSocket;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
using SqlSugar;
using WIDESEAWCS_BasicInfoRepository;
using WIDESEAWCS_BasicInfoService;
using WIDESEAWCS_Common;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.BasicInfo;
using WIDESEAWCS_DTO.PlacedBlockDTO;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_IBasicInfoRepository;
using WIDESEAWCS_IBasicInfoService;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Repository;
using static Dm.net.buffer.ByteArrayBuffer;
namespace WIDESEAWCS_TaskInfoService
{
///
/// 任务服务类,提供任务相关的业务逻辑操作
///
///
/// 主要功能包括:
/// 1. 查询门架设备未执行任务
/// 2. 执行订单块放置测试
/// 3. 创建和管理任务
/// 4. 生成和重新生成任务
/// 5. 处理异常任务
/// 6. 任务完成处理
/// 依赖仓储层进行数据访问,通过工作单元管理事务
/// 使用WebSocket进行实时通知,并包含完整的异常处理机制
///
public class TaskService : ServiceBase, ITaskService
{
///
/// 工作单元管理接口实例,用于管理数据库事务和工作单元
///
private readonly IUnitOfWorkManage _unitOfWorkManage;
///
/// 用于对象映射的映射器实例
///
private readonly IMapper _mapper;
///
/// 容器仓储接口实例,用于容器相关数据操作
///
private readonly IContainerRepository _containerRepository;
///
/// 容器物品仓储接口实例(只读)
///
private readonly IContainerItemRepository _containerItemRepository;
///
/// WebSocket服务器实例,用于处理WebSocket连接
///
private readonly WebSocketServer _webSocketServer;
///
/// 订单详情仓储接口实例(只读)
///
private readonly IOrderDetailsRepository _orderDetailsRepository;
///
/// 容器服务接口实例,用于管理依赖注入容器相关操作
///
private readonly IContainerService _containerService;
///
/// 订单明细服务接口
///
private readonly IOrderDetailsService _orderDetailsService;
///
/// 订单行仓储接口实例,用于操作订单行数据
///
private readonly IOrderrowsRepository _orderrowsRepository;
///
/// 订单容器仓储接口实例,用于操作订单容器相关数据
///
private readonly IOrderContainerRepository _orderContainerRepository;
public TaskService(ITaskRepository BaseDal, IUnitOfWorkManage unitOfWorkManage, IMapper mapper, IContainerRepository containerRepository, IContainerItemRepository containerItemRepository, WebSocketServer webSocketServer, IOrderDetailsRepository orderDetailsRepository, IContainerService containerService, IOrderDetailsService orderDetailsService, IOrderrowsRepository orderrowsRepository, IOrderContainerRepository orderContainerRepository) : base(BaseDal)
{
_unitOfWorkManage = unitOfWorkManage;
_mapper = mapper;
_containerRepository = containerRepository;
_containerItemRepository = containerItemRepository;
_webSocketServer = webSocketServer;
_orderDetailsRepository = orderDetailsRepository;
_containerService = containerService;
_orderDetailsService = orderDetailsService;
_orderrowsRepository = orderrowsRepository;
_orderContainerRepository = orderContainerRepository;
}
///
/// 查询指定门架设备未执行的任务
///
/// 门架设备编号
/// 未执行的任务数据,若不存在则返回null
public Dt_Task? QueryAGantryUnExecuteTask(string gantryDeviceNo)
{
return BaseDal.QueryFirst(x => x.TaskState == (int)TaskStatusEnum.Gantry_New && x.DeviceCode == gantryDeviceNo);
}
///
/// 执行订单块放置测试,根据订单行ID获取订单明细并计算放置位置
///
/// 订单行ID
/// 包含放置块信息的Web响应内容。成功时返回放置块列表,失败时返回错误信息
///
/// 1. 通过订单行ID查询订单明细数据
/// 2. 对每个有效订单明细计算合适的放置位置
/// 3. 创建容器项和任务记录
/// 4. 通过WebSocket发布放置位置信息
/// 5. 返回所有成功放置的块信息
///
public WebResponseContent PlaceBlockTest(int orderRowId)
{
try
{
List orderDetails = _orderDetailsRepository.QueryData(x => x.Orderrowsid == orderRowId);
if (orderDetails == null || orderDetails.Count == 0)
{
return WebResponseContent.Instance.Error("未找到订单明细信息");
}
List placedBlocks = new List();
string putPosition = "";
for (int i = 0; i < orderDetails.Count; i++)
{
try
{
lock (placedBlocks)
{
int length = Convert.ToInt32(orderDetails[i].Orderdetails_length);
int width = Convert.ToInt32(orderDetails[i].Orderdetails_width);
int height = Convert.ToInt32(orderDetails[i].Orderdetails_thickness);
OrderInfo orderInfo = _orderDetailsService.GetOrderInfoByBarcode(orderDetails[i].Orderdetails_outid);
var (flag, taskPosition, message) = _containerService.GetPosition(orderInfo.OrderHeadId, orderInfo.OrderNo, length, width, height);
if (flag && taskPosition != null)
{
if (string.IsNullOrEmpty(putPosition))
{
putPosition = taskPosition.PutPosition;
}
if (putPosition != taskPosition.PutPosition)
{
continue;
}
Dt_OrderContainer orderContainer = _orderContainerRepository.QueryFirst(x => x.OrderNo == orderInfo.OrderNo && x.ContainerCode == taskPosition.PutPosition);
Dt_Container putContainer = _containerRepository.QueryFirst(x => x.ContainerCode == taskPosition.PutPosition);
if (putContainer == null)
{
//todo
throw new Exception("未找到放货位置");
}
bool isAdd = false;
if (orderContainer == null)
{
orderContainer = new Dt_OrderContainer()
{
OrderId = orderInfo.OrderHeadId,
ContainerCode = putContainer.ContainerCode,
ContainerId = putContainer.Id,
OrderNo = orderInfo.OrderNo,
};
int containerLength = putContainer.ContainerLength;
int containerWidth = putContainer.ContainerWidth;
int maxValue = Math.Max(length, width);
int minValue = Math.Min(length, width);
if (minValue > putContainer.ContainerWidth)
{
containerLength = maxValue;
containerWidth = minValue;
}
orderContainer.MaxLength = containerLength;
orderContainer.MaxWidth = containerWidth;
isAdd = true;
}
if (taskPosition != null)
{
Dt_ContainerItem dt_ContainerItem = new Dt_ContainerItem()
{
ContainerId = putContainer.Id,
ItemCode = orderInfo.Barcode,
ItemLength = length,
ItemWidth = width,
ItemHeight = height,
ItemPositionX = taskPosition.PositionX,
ItemPositionY = taskPosition.PositionY,
ItemPositionZ = taskPosition.PositionZ,
ItemRelaPositionX = taskPosition.PutPositionX,
ItemRelaPositionY = taskPosition.PutPositionY,
ItemRelaPositionZ = taskPosition.PutPositionZ,
ItemStatus = (int)ItemStatusEnum.Assigned,
ItemName = orderInfo.Barcode
};
Dt_Task dt_Task = new Dt_Task()
{
PalletCode = orderInfo.Barcode,
DeviceCode = putContainer.DeviceCode,
TaskState = (int)TaskStatusEnum.Gantry_Wait,
TaskType = 0,
SourceAddress = "",
TargetAddress = $"F06",
CurrentAddress = $"F06*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}",
NextAddress = $"{putContainer.ContainerCode}*{taskPosition.PutPositionX}*{taskPosition.PutPositionY}*{taskPosition.PutPositionZ}*{taskPosition.PositionR}",
ItemInfo = $"{length}*{width}*{height}",
Grade = 0,
};
putContainer.ContainerStatus = ContainerStatusEnum.NonEmpty.ObjToInt();
_unitOfWorkManage.BeginTran();
BaseDal.AddData(dt_Task);
_containerRepository.UpdateData(putContainer);
_containerItemRepository.AddData(dt_ContainerItem);
if (isAdd)
{
_orderContainerRepository.AddData(orderContainer);
}
_unitOfWorkManage.CommitTran();
PlacedBlock placedBlock = new PlacedBlock(new Point3D(taskPosition.PositionX, taskPosition.PositionY, taskPosition.PositionZ), length > width ? length : width, width > length ? length : width, height);
placedBlocks.Add(placedBlock);
Thread.Sleep(1000);
object obj = new
{
x = taskPosition.PutCenterPositionX - putContainer.ContainerLength / 2,
y = taskPosition.PutCenterPositionY - putContainer.ContainerWidth / 2,
z = taskPosition.PutPositionZ,
length = length > width ? length : width,
width = width > length ? length : width,
height,
};
_webSocketServer.PublishAllClientPayload(obj.Serialize());
}
}
}
}
catch (Exception ex)
{
}
}
return WebResponseContent.Instance.OK(data: placedBlocks);
}
catch (Exception ex)
{
return WebResponseContent.Instance.Error(ex.Message);
}
}
///
/// 创建任务并计算物品放置位置
///
/// 取货位置编码
/// 放货位置编码
/// 设备编码
/// 物品长度
/// 物品宽度
/// 物品高度
/// 包含操作结果的Web响应内容
///
/// 1. 验证取货/放货位置是否存在
/// 2. 计算物品在容器中的最佳放置位置
/// 3. 创建容器物品记录和任务记录
/// 4. 通过WebSocket通知客户端
///
public WebResponseContent CreateTask(string takePosition, string putPosition, string deviceCode, int length, int width, int height)
{
try
{
Dt_Container takeContainer = _containerRepository.QueryFirst(x => x.ContainerCode == takePosition && x.ContainerType == ContainerTypeEnum.TakeContainer.ObjToInt());
if (takeContainer == null)
{
return WebResponseContent.Instance.Error("取货位置不存在");
}
List containers = _containerRepository.QueryData(x => x.DeviceCode == deviceCode && x.ContainerType == ContainerTypeEnum.PutContainer.ObjToInt());
Dt_Container putContainer = _containerRepository.QueryFirst(x => x.ContainerCode == putPosition && x.ContainerType == ContainerTypeEnum.PutContainer.ObjToInt());
if (putContainer == null)
{
return WebResponseContent.Instance.Error("放货位置不存在");
}
int edge = 0;
if (putContainer.ContainerNo == containers.Min(x => x.ContainerNo))
{
edge = 1;
}
ContainerSize containerSize = new ContainerSize(putContainer.ContainerLength, putContainer.ContainerWidth, putContainer.ContainerHeight);
List containerItems = _containerItemRepository.QueryData(x => x.ContainerId == putContainer.Id);
List placedBlocks = containerItems.Select(x => new PlacedBlock(new Point3D(x.ItemPositionX, x.ItemPositionY, x.ItemPositionZ), x.ItemLength > x.ItemLength ? x.ItemLength : x.ItemWidth, x.ItemLength > x.ItemLength ? x.ItemWidth : x.ItemLength, x.ItemHeight)).ToList();
TaskPosition? taskPosition = _containerService.GetTaskPosition(length, width, height, containerSize, placedBlocks, edge);
if (taskPosition == null)
{
return WebResponseContent.Instance.Error("未找到合适放置位置");
}
object obj = new
{
x = taskPosition.PutCenterPositionX - putContainer.ContainerLength / 2,
y = taskPosition.PutCenterPositionY - putContainer.ContainerWidth / 2,
z = taskPosition.PutCenterPositionZ,
length,
width,
height,
};
_webSocketServer.PublishAllClientPayload(obj.Serialize());
string code = DateTime.Now.ToString("yyyyMMddHHmmss");
Dt_ContainerItem dt_ContainerItem = new Dt_ContainerItem()
{
ContainerId = putContainer.Id,
ItemCode = code,
ItemLength = length,
ItemWidth = width,
ItemHeight = height,
ItemPositionX = taskPosition.PositionX,
ItemPositionY = taskPosition.PositionY,
ItemPositionZ = taskPosition.PositionZ,
ItemRelaPositionX = taskPosition.PutPositionX,
ItemRelaPositionY = taskPosition.PutPositionY,
ItemRelaPositionZ = taskPosition.PutPositionZ,
ItemStatus = (int)ItemStatusEnum.Assigned,
ItemName = code
};
Dt_Task dt_Task = new Dt_Task()
{
PalletCode = code,
DeviceCode = putContainer.DeviceCode,
TaskState = (int)TaskStatusEnum.Gantry_New,
TaskType = 0,
SourceAddress = "",
TargetAddress = $"{takeContainer.ContainerNo}",
CurrentAddress = $"{takeContainer.ContainerCode}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}",
NextAddress = $"{putContainer.ContainerCode}*{taskPosition.PutPositionX}*{taskPosition.PutPositionY}*{taskPosition.PutPositionZ}*{taskPosition.PositionR}",
ItemInfo = $"{length}*{width}*{height}",
Grade = 0,
};
_containerItemRepository.AddData(dt_ContainerItem);
base.AddData(dt_Task);
return WebResponseContent.Instance.OK();
}
catch (Exception ex)
{
return WebResponseContent.Instance.Error(ex.Message);
}
}
///
/// 根据订单信息生成任务
///
/// 订单信息
/// 包含三个值的元组:
/// Item1 - 操作是否成功 (bool)
/// Item2 - 生成的任务对象 (Dt_Task),失败时为null
/// Item3 - 错误消息 (string),成功时为空字符串
///
///
/// 该方法会:
/// 1. 根据订单尺寸获取合适的货位
/// 2. 创建容器项和任务记录
/// 3. 更新相关容器状态
/// 4. 在事务中执行所有数据库操作
///
public (bool, Dt_Task?, string) GenerateTask(OrderInfo orderInfo)
{
try
{
int length = Convert.ToInt32(orderInfo.Length);
int width = Convert.ToInt32(orderInfo.Width);
int height = Convert.ToInt32(orderInfo.Thickness);
var (flag, taskPosition, message) = _containerService.GetPosition(orderInfo.OrderHeadId, orderInfo.OrderNo, length, width, height);
if (flag && taskPosition != null)
{
Dt_Container putContainer = _containerRepository.QueryFirst(x => x.ContainerCode == taskPosition.PutPosition);
if (putContainer == null)
{
return (false, null, "未找到放货位置");
}
Dt_Container? takeContainer = GetTakePosition(putContainer.DeviceCode);
if (takeContainer == null)
{
return (false, null, "未找到取货位置");
}
Dt_OrderContainer orderContainer = _orderContainerRepository.QueryFirst(x => x.OrderNo == orderInfo.OrderNo && x.ContainerCode == putContainer.ContainerCode);
bool isAdd = false;
bool isUpdate = false;
if (orderContainer == null)
{
orderContainer = new Dt_OrderContainer()
{
OrderId = orderInfo.OrderHeadId,
ContainerCode = putContainer.ContainerCode,
ContainerId = putContainer.Id,
OrderNo = orderInfo.OrderNo,
};
int containerLength = putContainer.ContainerLength;
int containerWidth = putContainer.ContainerWidth;
int maxValue = Math.Max(length, width);
int minValue = Math.Min(length, width);
if (minValue > putContainer.ContainerWidth)
{
containerLength = maxValue;
containerWidth = minValue;
}
orderContainer.MaxLength = containerLength;
orderContainer.MaxWidth = containerWidth;
isAdd = true;
}
Dt_ContainerItem dt_ContainerItem = new Dt_ContainerItem()
{
ContainerId = putContainer.Id,
ItemCode = orderInfo.Barcode,
ItemLength = length,
ItemWidth = width,
ItemHeight = height,
ItemPositionX = taskPosition.PositionX,
ItemPositionY = taskPosition.PositionY,
ItemPositionZ = taskPosition.PositionZ,
ItemRelaPositionX = taskPosition.PutPositionX,
ItemRelaPositionY = taskPosition.PutPositionY,
ItemRelaPositionZ = taskPosition.PutPositionZ,
ItemStatus = (int)ItemStatusEnum.Assigned,
ItemName = orderInfo.Barcode,
Remark = $"{takeContainer.ContainerCode}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}"
};
Dt_Task dt_Task = new Dt_Task()
{
PalletCode = orderInfo.Barcode,
DeviceCode = putContainer.DeviceCode,
TaskState = (int)TaskStatusEnum.Gantry_Wait,
TaskType = 0,
SourceAddress = "",
TargetAddress = $"{takeContainer.ContainerNo}",
CurrentAddress = $"{takeContainer.ContainerCode}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}",
NextAddress = $"{putContainer.ContainerCode}*{taskPosition.PutPositionX}*{taskPosition.PutPositionY}*{taskPosition.PutPositionZ}*{taskPosition.PositionR}",
ItemInfo = $"{length}*{width}*{height}",
Grade = 0,
};
putContainer.ContainerStatus = ContainerStatusEnum.NonEmpty.ObjToInt();
_unitOfWorkManage.BeginTran();
BaseDal.AddData(dt_Task);
_containerRepository.UpdateData(putContainer);
_containerItemRepository.AddData(dt_ContainerItem);
if (isAdd)
{
_orderContainerRepository.AddData(orderContainer);
}
else if (isUpdate)
{
_orderContainerRepository.UpdateData(orderContainer);
}
_unitOfWorkManage.CommitTran();
return (true, dt_Task, "");
}
else
{
return (false, null, message);
}
}
catch (Exception ex)
{
_unitOfWorkManage.RollbackTran();
return (false, null, $"错误,{ex.ExceptionToString()}");
}
}
///
/// 重新生成任务
///
/// 原始任务对象
/// 工作站编码
///
/// 包含三个值的元组:
/// 1. bool - 操作是否成功
/// 2. Dt_Task - 更新后的任务对象(失败时为null)
/// 3. string - 错误消息(成功时为空字符串)
///
///
/// 该方法用于重新生成任务信息,包括:
/// 1. 解析板子尺寸信息
/// 2. 验证取货/放货位置
/// 3. 计算物品放置位置
/// 4. 更新任务状态和位置信息
/// 5. 在事务中更新数据库记录
///
public (bool, Dt_Task?, string) RegenerateTask(Dt_Task task, string stationCode)
{
try
{
int length = 0;
int width = 0;
int height = 0;
Dt_ContainerItem containerItem = _containerItemRepository.QueryFirst(x => x.ItemCode == task.PalletCode);
if (containerItem == null)
{
List itemInfos = task.ItemInfo.Split("*").ToList();
if (itemInfos.Count == 3)
{
length = Convert.ToInt32(itemInfos[0]);
width = Convert.ToInt32(itemInfos[1]);
height = Convert.ToInt32(itemInfos[2]);
}
else
{
return (false, null, "板子尺寸信息错误");
}
}
else
{
length = containerItem.ItemLength;
width = containerItem.ItemWidth;
height = containerItem.ItemHeight;
}
string containerCode = task.NextAddress.Split("*")[0];
Dt_Container putContainer = _containerRepository.QueryFirst(x => x.ContainerCode == containerCode);
if (putContainer == null)
{
return (false, null, "未找到放货位置");
}
Dt_Container? takeContainer = _containerRepository.QueryFirst(x => x.ContainerCode == stationCode);
if (takeContainer == null)
{
return (false, null, "未找到取货位置");
}
var (flag, taskPosition, message) = _containerService.GetPosition(putContainer, length, width, height);
if (!flag || taskPosition == null)
{
return (false, null, message);
}
Dt_OrderContainer orderContainer = _orderContainerRepository.QueryFirst(x => x.ContainerCode == putContainer.ContainerCode);
bool isAdd = false;
if (orderContainer == null)
{
return (false, null, "未找到订单与容器绑定关系");
}
int containerLength = putContainer.ContainerLength;
int containerWidth = putContainer.ContainerWidth;
int maxValue = Math.Max(length, width);
int minValue = Math.Min(length, width);
if (minValue > putContainer.ContainerWidth)
{
containerLength = maxValue;
containerWidth = minValue;
}
orderContainer.MaxLength = containerLength;
orderContainer.MaxWidth = containerWidth;
if (containerItem == null)
{
containerItem = new Dt_ContainerItem()
{
ContainerId = putContainer.Id,
ItemCode = task.PalletCode,
ItemLength = length,
ItemWidth = width,
ItemHeight = height,
ItemPositionX = taskPosition.PositionX,
ItemPositionY = taskPosition.PositionY,
ItemPositionZ = taskPosition.PositionZ,
ItemRelaPositionX = taskPosition.PutPositionX,
ItemRelaPositionY = taskPosition.PutPositionY,
ItemRelaPositionZ = taskPosition.PutPositionZ,
ItemStatus = (int)ItemStatusEnum.Assigned,
ItemName = task.PalletCode,
Remark = $"{takeContainer.ContainerCode}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}"
};
isAdd = true;
}
else
{
containerItem.ItemLength = length;
containerItem.ItemWidth = width;
containerItem.ItemHeight = height;
containerItem.ItemPositionX = taskPosition.PositionX;
containerItem.ItemPositionY = taskPosition.PositionY;
containerItem.ItemPositionZ = taskPosition.PositionZ;
containerItem.ItemRelaPositionX = taskPosition.PutPositionX;
containerItem.ItemRelaPositionY = taskPosition.PutPositionY;
containerItem.ItemRelaPositionZ = taskPosition.PutPositionZ;
containerItem.ItemStatus = (int)ItemStatusEnum.Assigned;
containerItem.Remark = $"{takeContainer.ContainerCode}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}";
}
task.TaskState = (int)TaskStatusEnum.Gantry_New;
task.CurrentAddress = $"{takeContainer.ContainerCode}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}";
task.NextAddress = $"{putContainer.ContainerCode}*{taskPosition.PutPositionX}*{taskPosition.PutPositionY}*{taskPosition.PutPositionZ}*{taskPosition.PositionR}";
task.ItemInfo = $"{length}*{width}*{height}";
_unitOfWorkManage.BeginTran();
BaseDal.UpdateData(task);
_containerRepository.UpdateData(putContainer);
_orderContainerRepository.UpdateData(orderContainer);
if (isAdd)
{
_containerItemRepository.AddData(containerItem);
}
else
{
_containerItemRepository.UpdateData(containerItem);
}
_unitOfWorkManage.CommitTran();
return (true, task, "");
}
catch (Exception ex)
{
_unitOfWorkManage.RollbackTran();
return (false, null, $"错误,{ex.ExceptionToString()}");
}
}
///
/// 生成异常任务
///
/// 订单信息
/// 元组包含三个值:
/// Item1 - 操作是否成功(bool)
/// Item2 - 生成的任务对象(Dt_Task),失败时为null
/// Item3 - 错误消息(string),成功时为空字符串
///
/// 该方法会根据订单信息生成一个异常处理任务,包括:
/// 1. 获取异常位置
/// 2. 验证放货/取货位置
/// 3. 创建容器项和任务记录
/// 4. 提交事务
///
public (bool, Dt_Task?, string) GenerateExceptionTask(OrderInfo orderInfo)
{
int length = Convert.ToInt32(orderInfo.Length);
int width = Convert.ToInt32(orderInfo.Width);
int height = Convert.ToInt32(orderInfo.Thickness);
var (flag, taskPosition, message) = _containerService.GetExceptionPosition(length, width, height);
if (flag && taskPosition != null)
{
Dt_Container putContainer = _containerRepository.QueryFirst(x => x.ContainerCode == taskPosition.PutPosition);
if (putContainer == null)
{
return (false, null, "未找到放货位置");
}
Dt_Container? takeContainer = GetTakePosition(putContainer.DeviceCode);
if (takeContainer == null)
{
return (false, null, "未找到取货位置");
}
Dt_ContainerItem dt_ContainerItem = new Dt_ContainerItem()
{
ContainerId = putContainer.Id,
ItemCode = orderInfo.Barcode,
ItemLength = length,
ItemWidth = width,
ItemHeight = height,
ItemPositionX = taskPosition.PositionX,
ItemPositionY = taskPosition.PositionY,
ItemPositionZ = taskPosition.PositionZ,
ItemRelaPositionX = taskPosition.PutPositionX,
ItemRelaPositionY = taskPosition.PutPositionY,
ItemRelaPositionZ = taskPosition.PutPositionZ,
ItemStatus = (int)ItemStatusEnum.Assigned,
ItemName = orderInfo.Barcode,
Remark = $"{takeContainer.ContainerCode}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}"
};
Dt_Task dt_Task = new Dt_Task()
{
PalletCode = orderInfo.Barcode,
DeviceCode = putContainer.DeviceCode,
TaskState = (int)TaskStatusEnum.Gantry_Wait,
TaskType = 0,
SourceAddress = "",
TargetAddress = $"{takeContainer.ContainerNo}",
CurrentAddress = $"{takeContainer.ContainerCode}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}",
NextAddress = $"{putContainer.ContainerCode}*{taskPosition.PutPositionX}*{taskPosition.PutPositionY}*{taskPosition.PutPositionZ}*{taskPosition.PositionR}",
ItemInfo = $"{length}*{width}*{height}",
Grade = 0,
};
if (taskPosition.TakeCenterPositionZ == 99)
{
dt_Task.TaskState = (int)TaskStatusEnum.Gantry_BeRelease;
}
_unitOfWorkManage.BeginTran();
BaseDal.AddData(dt_Task);
_containerItemRepository.AddData(dt_ContainerItem);
_unitOfWorkManage.CommitTran();
return (true, dt_Task, "");
}
else
{
return (false, null, message);
}
}
///
/// 根据设备编号获取取货位置
///
/// 设备编号
/// 符合条件的容器对象,若找不到则返回null
///
/// 1. 首先查询指定设备下所有可用的取货容器,并按ContainerSort升序排序
/// 2. 查找该设备最近的任务记录
/// 3. 如果找到任务记录,则根据任务源地址匹配容器,返回下一个容器(若已是最后一个则返回第一个)
/// 4. 如果出现异常或未找到匹配项,则返回第一个可用容器
///
public Dt_Container? GetTakePosition(string deviceCode)
{
Dictionary orderby = new Dictionary() { { nameof(Dt_Container.ContainerSort), OrderByType.Asc } };
List containers = _containerRepository.QueryData(x => x.ContainerType == ContainerTypeEnum.TakeContainer.ObjToInt() && x.DeviceCode == deviceCode && x.ContainerEnable, orderby);
try
{
if (containers == null || containers.Count == 0)
{
throw new Exception($"未找到对应的取货位置,设备编号:{deviceCode}");
}
Dictionary taskOrderby = new Dictionary() { { nameof(Dt_Task.TaskNum), OrderByType.Desc } };
Dt_Task task = BaseDal.QueryFirst(x => x.DeviceCode == deviceCode, taskOrderby);
if (task != null)
{
string? sourceCode = task.SourceAddress.Split("*").FirstOrDefault();
if (!string.IsNullOrEmpty(sourceCode))
{
Dt_Container? container = containers.FirstOrDefault(x => x.ContainerCode == sourceCode);
if (container != null)
{
int index = containers.IndexOf(container);
if (index + 1 < containers.Count)
{
return containers[index + 1];
}
else
{
return containers.FirstOrDefault();
}
}
}
}
}
catch (Exception ex)
{
}
return containers.FirstOrDefault();
}
///
/// 任务完成处理方法
///
/// 任务实体
/// Web响应内容
///
/// 1. 更新任务状态为"龙门架完成"
/// 2. 更新相关订单详情状态为"码垛成功"
/// 3. 更新订单行中的托盘数量
/// 4. 根据任务完成情况发送WebSocket通知
/// 5. 记录操作日志并提交事务
/// 6. 异常时回滚事务并返回错误信息
///
public WebResponseContent TaskComplete(Dt_Task task)
{
try
{
task.TaskState = TaskStatusEnum.Gantry_Completed.ObjToInt();
_unitOfWorkManage.BeginTran();
OrderDetails orderDetails = _orderDetailsRepository.QueryFirst(x => x.Orderdetails_outid == task.PalletCode);
if (orderDetails != null)
{
orderDetails.Orderdetails_status = PalletingStatusEnmu.PalletingSuccess.ObjToInt();
Orderrows orderrows = _orderrowsRepository.QueryFirst(x => x.id == orderDetails.Orderrowsid);
if (orderrows != null)
{
orderrows.Orderrows_PalletNum = orderrows.Orderrows_PalletNum ?? 0 + 1;
Dt_Container container = _containerRepository.QueryFirst(x => task.NextAddress.Contains(x.ContainerCode));
_orderDetailsRepository.UpdateData(orderDetails);
_orderrowsRepository.UpdateData(orderrows);
if (container.ContainerType == ContainerTypeEnum.ExceptionContainer.ObjToInt())
{
int count = Db.Queryable().Count(x => x.ContainerId == container.Id);
if (count >= 5)
{
if (LightStatusStorage.LightStatusDic.ContainsKey(container.ContainerCode))
{
LightStatusStorage.LightStatusDic[container.ContainerCode] = LightStatusEnum.LightError;
}
}
}
try
{
List containerItemCodes = _containerItemRepository.QueryData(x => x.ContainerId == container.Id).Select(x => x.ItemCode).ToList();
List totalDetails = _orderDetailsRepository.QueryData(x => x.Orderrowsid == orderrows.id);
List details = totalDetails.Where(x => x.Orderrowsid == orderrows.id && x.Orderdetails_status == PalletingStatusEnmu.PalletingSuccess.ObjToInt() && containerItemCodes.Contains(x.Orderdetails_outid)).ToList();
int sortedNum = totalDetails.Where(x => x.Orderrowsid == orderrows.id && x.Orderdetails_status == PalletingStatusEnmu.PalletingSuccess.ObjToInt()).Count();
List