namespace WIDESEA_StorageOutTaskServices; public class Dt_TaskService : ServiceBase, IDt_TaskService { private readonly LogFactory LogFactory = new LogFactory(); private readonly IUnitOfWorkManage _unitOfWorkManage; private readonly IDt_OutOrderRepository _outOrderRepository; private readonly IDt_BillGroupStockRepository _billGroupStockRepository; private readonly IDt_Task_HtyRepository _task_HtyRepository; private readonly IDt_OutOrderAndStockRepository _outOrderAndStockRepository; private readonly IDt_OutOrderAndStock_HtyRepository _outOrderAndStock_HtyRepository; private readonly IMapper _mapper; private readonly IDt_MaterielInfoRepository _materielInfoRepository; private readonly IDt_LocationRepository _locationRepository; public Dt_TaskService(IDt_TaskRepository BaseDal, IUnitOfWorkManage unitOfWorkManage, IDt_OutOrderRepository outOrderRepository, IDt_BillGroupStockRepository billGroupStockRepository, IDt_OutOrderAndStockRepository dt_OutOrderAndStockRepository, IDt_OutOrderAndStock_HtyRepository dt_OutOrderAndStock_HtyRepository, IDt_Task_HtyRepository task_HtyRepository, IMapper mapper, IDt_MaterielInfoRepository materielInfoRepository, IDt_LocationRepository locationRepository) : base(BaseDal) { _unitOfWorkManage = unitOfWorkManage; _outOrderRepository = outOrderRepository; _billGroupStockRepository = billGroupStockRepository; _outOrderAndStockRepository = dt_OutOrderAndStockRepository; _outOrderAndStock_HtyRepository = dt_OutOrderAndStock_HtyRepository; _task_HtyRepository = task_HtyRepository; _mapper = mapper; _materielInfoRepository = materielInfoRepository; _locationRepository = locationRepository; } #region 外部接口方法 /// /// 堆垛机任务完成 /// /// 任务数据合集 /// 返回结果集 public async Task CompleteStackTaskAsync(Dt_Task task, Dt_BillGroupStock stock) { WebResponseContent content = new WebResponseContent(); try { // 更新库存状态 stock.LocationCode = null; stock.LocationInfo.Status = LocationEnum.Free.ObjToInt(); stock.OrderType = 2; // 更新任务状态 task.TaskState = OutTaskStatusEnum.SC_OutFinish.ObjToInt(); task.CurrentAddress = task.NextAddress; task.NextAddress = task.TargetAddress; LogFactory.GetLog("任务完成").InfoFormat(true, "堆垛机出库完成", "更新库存状态与任务状态"); // 事务处理 _unitOfWorkManage.BeginTran(); var isStockUpdated = _billGroupStockRepository.UpdateNavStock(stock); var isTaskUpdated = await Update(task); if (isStockUpdated && isTaskUpdated) { LogFactory.GetLog("任务完成").InfoFormat(true, "堆垛机出库完成", $"事务处理完成,库存状态更新:{isStockUpdated},任务状态更新:{isTaskUpdated}"); _unitOfWorkManage.CommitTran(); return content.OK("任务完成成功"); } else { LogFactory.GetLog("任务完成").InfoFormat(true, "堆垛机出库完成", $"事务处理失败,库存状态更新:{isStockUpdated},任务状态更新:{isTaskUpdated}"); _unitOfWorkManage.RollbackTran(); return content.Error("任务或库存更新失败"); } } catch (Exception err) { LogFactory.GetLog("任务完成").InfoFormat(true, $"系统异常,异常信息:{err.Message}", ""); Console.WriteLine(err.Message); return content.Error(err.Message); } } /// /// 出库任务完成 /// /// 任务数据合集 /// 返回结果集 public async Task CompleteTaskAsync(Dt_Task task, Dt_BillGroupStock stock) { WebResponseContent content = new WebResponseContent(); try { // 更新出库订单和库存货位信息 var orderStock = await UpdateOrderAndStockAsync(stock, task.PalletCode); LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成", $"更新出库订单和库存货位信息:{JsonConvert.SerializeObject(orderStock)}"); // 检查订单是否完成并处理后续操作 if (IsOrderComplete(orderStock)) { LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成", $"订单出库完成"); // 处理已完成订单 await ProcessCompletedOrderAsync(orderStock, task); } else { LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成", $"订单暂未出库完成"); // 处理未完成订单 await ProcessUpdateOrderAsync(orderStock, task); } content.OK("任务完成"); } catch (Exception err) { // 记录异常信息 Console.WriteLine(err.Message.ToString()); content.Error("任务完成失败"); } return content; } /// /// 移库任务完成 /// /// 任务数据合集 /// 返回结果集 public async Task CompleteTransferTaskAsync(Dt_Task task, Dt_BillGroupStock stock) { WebResponseContent content = new WebResponseContent(); try { // 更新货位和库存信息 (Dt_BillGroupStock updateStock, Dt_LocationInfo locationInf) = UpdateStockLocation(stock, task.NextAddress); var taskHty = CreateHistoricalTask(task); LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"修改后库存数据:{JsonConvert.SerializeObject(updateStock)},原先货位数据:{locationInf}"); // 执行数据库事务 bool isResult = await ExecuteTransaction(updateStock, taskHty, locationInf, task.TaskId); if (isResult) content.OK("移库任务完成成功"); else content.Error("移库任务完成失败"); } catch (Exception err) { Console.WriteLine(err.Message.ToString()); } return content; } /// /// 任务完成 /// /// 任务号 /// public async Task CompleteAsync(int taskNum) { WebResponseContent content = new WebResponseContent(); // 提取任务数据 LogFactory.GetLog("任务完成").InfoFormat(true, "提取任务数据", $"任务号:{taskNum}"); // 验证任务是否存在 var task = await GetByTaskNum(taskNum); if (task == null) { return content.Error("任务不存在"); } LogFactory.GetLog("任务完成").InfoFormat(true, "验证任务是否存在", JsonConvert.SerializeObject(task)); // 验证库存是否存在 var stock = await _billGroupStockRepository.GetStocksAsync(palletCode: task.PalletCode); if (stock == null) { return content.Error("库存不存在"); } LogFactory.GetLog("任务完成").InfoFormat(true, "验证库存是否存在", JsonConvert.SerializeObject(stock)); if (task.TaskType == (int)TaskTypeEnum.Outbound) { LogFactory.GetLog("任务完成").InfoFormat(true, "出库任务", ""); if (task.TaskState == OutTaskStatusEnum.SC_OutExecuting.ObjToInt()) { LogFactory.GetLog("任务完成").InfoFormat(true, "堆垛机出库完成", ""); return await CompleteStackTaskAsync(task, stock); } else { LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成", ""); return await CompleteTaskAsync(task, stock); } } else if (task.TaskType == (int)TaskTypeEnum.RelocationIn) { LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", ""); return await CompleteTransferTaskAsync(task, stock); } else { LogFactory.GetLog("任务完成").InfoFormat(true, $"任务状态异常", "无参数"); return content.Error("任务状态异常"); } } /// /// 获取所有可出库库存,分配出库。 /// /// 出库库存列表 #endregion 外部接口方法 #region 内部调用方法 /// /// 创建一个新的任务 /// /// 任务模型 /// 创建的任务 public async Task Create(Dt_Task model) { return await BaseDal.Create(model); } /// /// 批量创建任务 /// /// 任务模型列表 /// 是否创建成功 public async Task Create(List models) { return await BaseDal.Create(models); } /// /// 删除一个任务 /// /// 任务ID /// 是否删除成功 public async Task Delete(int id) { return await BaseDal.Delete(id); } /// /// 批量删除任务 /// /// 任务ID列表 /// 是否删除成功 public async Task Delete(List ids) { return await BaseDal.Delete(ids); } /// /// 通过ID获取任务 /// /// 任务ID /// 任务模型 public async Task GetById(int id) { return await BaseDal.GetById(id); } /// /// 获取所有任务列表 /// /// 任务模型列表 public async Task> GetList() { return await BaseDal.GetList(); } /// /// 根据出库订单ID获取任务列表 /// /// 出库订单ID /// 任务模型列表 public async Task> GetListByOutOrder(int outOrderId) { return await BaseDal.GetListByOutOrder(outOrderId); } /// /// 根据出库订单ID和状态获取任务列表 /// /// 出库订单ID /// 任务状态 /// 任务模型列表 public async Task> GetListByOutOrderAndStatus(int outOrderId, int status) { return await BaseDal.GetListByOutOrderAndStatus(outOrderId, status); } /// /// 根据状态获取任务列表 /// /// 任务状态 /// 任务模型列表 public async Task> GetListByStatus(int status) { return await BaseDal.GetListByStatus(status); } /// /// 更新一个任务 /// /// 任务模型 /// 是否更新成功 public async Task Update(Dt_Task model) { return await BaseDal.Update(model); } /// /// 批量更新任务 /// /// 任务模型列表 /// 是否更新成功 public async Task Update(List models) { return await BaseDal.Update(models); } /// /// 检查任务是否存在 /// /// 托盘编码 /// 任务是否存在 public bool IsExist(string palletCode) { return Db.Queryable().Any(x => x.PalletCode == palletCode); } /// /// 根据货位ID获取任务 /// /// /// public async Task GetByLocation(string locationID) { return await Db.Queryable().Where(x => x.SourceAddress == locationID).FirstAsync(); } /// /// 根据任务号获取任务 /// /// /// public async Task GetByTaskNum(int taskNum) { return await Db.Queryable().Where(x => x.TaskNum == taskNum).FirstAsync(); } #endregion 内部调用方法 #region private 内部方法 /// /// 更新出库订单和库存信息 /// /// 库存实例 /// 条码 /// 更新后的订单和库存信息 private async Task UpdateOrderAndStockAsync(Dt_BillGroupStock stock, string barCode) { var orderStock = await _outOrderAndStockRepository.GetOrderAndStock(palletCode: barCode); orderStock.CompletedQuantity += stock.Dt_BillGroupStockDetailList.Sum(x => x.PalletQuantity).Value; orderStock.OrderList.OrderDetailList.CompletedQuantity += stock.Dt_BillGroupStockDetailList.Sum(x => x.PalletQuantity).Value; return orderStock; } /// /// 判断订单是否完成 /// /// 订单和库存信息 /// 是否完成 private bool IsOrderComplete(Dt_OutOrderAndStock orderStock) { return orderStock.CompletedQuantity == orderStock.OutboundQuantity; } /// /// 处理已完成的订单 /// /// 订单和库存信息 /// 任务数据 /// 异步任务 private async Task ProcessCompletedOrderAsync(Dt_OutOrderAndStock orderStock, Dt_Task task) { // 创建历史订单记录 var stockHty = CreateHistoricalOrder(orderStock); LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成,订单已完成", $"创建历史订单记录:{JsonConvert.SerializeObject(stockHty)}"); // 创建获取历史任务 var taskHty = CreateHistoricalTask(task); LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成,订单已完成", $"创建历史任务记录:{JsonConvert.SerializeObject(taskHty)}"); _unitOfWorkManage.BeginTran(); try { // 添加历史任务 var isTaskHtyAdd = await _task_HtyRepository.AddDataAsync(taskHty) > 0; // 删除任务数据 var isTaskDelete = await Delete(task.TaskId); // 插入历史订单 var isStockInsert = _outOrderAndStock_HtyRepository.InsertNav(stockHty); // 删除原订单 var isOrderStockDelete = _outOrderAndStockRepository.DeleteNavOrderStock(orderStock); if (isStockInsert && isOrderStockDelete && isTaskHtyAdd && isTaskDelete) { LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成,订单已完成", $"事务处理完成,提交事务。添加历史任务:{isTaskHtyAdd},删除任务数据:{isTaskDelete},插入历史订单:{isStockInsert},删除原订单:{isOrderStockDelete}"); _unitOfWorkManage.CommitTran(); } else { LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成,订单已完成", $"添加数据库失败,请检查数据是否正确,数据回滚。添加历史任务:{isTaskHtyAdd},删除任务数据:{isTaskDelete},插入历史订单:{isStockInsert},删除原订单:{isOrderStockDelete}"); _unitOfWorkManage.RollbackTran(); } } catch (Exception ex) { LogFactory.GetLog("任务完成").InfoFormat(true, $"总任务出库完成,订单已完成,系统异常,异常信息:{ex.Message}", "无参数"); _unitOfWorkManage.RollbackTran(); throw; // 重新抛出异常以供外部捕获 } } /// /// 处理未完成订单 /// /// 订单和库存信息 /// 任务数据 /// 异步任务 private async Task ProcessUpdateOrderAsync(Dt_OutOrderAndStock orderStock, Dt_Task task) { // 创建获取历史任务 var taskHty = CreateHistoricalTask(task); _unitOfWorkManage.BeginTran(); try { // 添加历史任务 var isTaskHtyAdd = await _task_HtyRepository.AddDataAsync(taskHty) > 0; // 删除任务数据 var isTaskDelete = await Delete(task.TaskId); // 更新订单与库存 var isOrderUpdated = _outOrderAndStockRepository.UpdateNavOrderStock(orderStock); if (isTaskDelete && isTaskHtyAdd && isOrderUpdated) { LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成,订单暂未完成", $"事务处理完成,提交事务。添加历史任务:{isTaskHtyAdd},删除任务数据:{isTaskDelete},更新订单与库存:{isOrderUpdated}"); _unitOfWorkManage.CommitTran(); } else { LogFactory.GetLog("任务完成").InfoFormat(true, "总任务出库完成,订单暂未完成", $"添加数据库失败,请检查数据是否正确,数据回滚。添加历史任务:{isTaskHtyAdd},删除任务数据:{isTaskDelete},更新订单与库存:{isOrderUpdated}"); _unitOfWorkManage.RollbackTran(); } } catch (Exception err) { LogFactory.GetLog("任务完成").InfoFormat(true, $"总任务出库完成,订单暂未完成,系统异常,异常信息:{err.Message}", "无参数"); Console.WriteLine(err.Message.ToString()); _unitOfWorkManage.RollbackTran(); throw; // 重新抛出异常以供外部捕获 } } /// /// 创建历史订单记录 /// /// 订单和库存信息 /// 历史订单记录 private Dt_OutOrderAndStock_Hty CreateHistoricalOrder(Dt_OutOrderAndStock orderStock) { var stockHty = _mapper.Map(orderStock); stockHty.StockList.FinishTime = DateTime.Now; stockHty.StockList.OperateType = (int)OperateTypeEnum.自动完成; stockHty.StockList.SourceId = orderStock.StockList.GroupId; stockHty.StockList.GroupId = 0; stockHty.StockList.StockDetailList.ForEach(x => { x.FinishTime = DateTime.Now; x.OperateType = (int)OperateTypeEnum.自动完成; x.GroupId = 0; }); stockHty.OrderList.FinishTime = DateTime.Now; stockHty.OrderList.OperateType = (int)OperateTypeEnum.自动完成; stockHty.OrderList.SourceId = orderStock.OrderList.Id; stockHty.OrderList.Id = 0; stockHty.OrderList.orderDetailList.FinishTime = DateTime.Now; stockHty.OrderList.orderDetailList.OperateType = (int)OperateTypeEnum.自动完成; stockHty.OrderList.orderDetailList.Id = 0; return stockHty; } private Dt_Task_Hty CreateHistoricalTask(Dt_Task task) { // 更新任务状态 task.TaskState = OutTaskStatusEnum.OutFinish.ObjToInt(); task.CurrentAddress = task.NextAddress; // 创建历史任务 var taskHty = _mapper.Map(task); taskHty.FinishTime = DateTime.Now; taskHty.TaskId = 0; taskHty.OperateType = (int)OperateTypeEnum.自动完成; taskHty.SourceId = task.TaskId; taskHty.TaskState = OutTaskStatusEnum.OutFinish.ObjToInt(); return taskHty; } /// /// 更新库存位置 /// /// 库存对象 /// 目标位置 private (Dt_BillGroupStock, Dt_LocationInfo) UpdateStockLocation(Dt_BillGroupStock stock, string toLocation) { var locationInfo = _locationRepository.QueryFirst(x => x.LocationCode == stock.LocationCode); locationInfo.Status = LocationEnum.InStock.ObjToInt(); stock.LocationCode = toLocation; stock.LocationInfo.Status = LocationEnum.InStock.ObjToInt(); return (stock, locationInfo); } /// /// 执行数据库事务 /// /// 库存对象 /// 历史任务对象 /// 任务ID /// private async Task ExecuteTransaction(Dt_BillGroupStock stock, Dt_Task_Hty taskHty, Dt_LocationInfo locationInfo, int taskId) { _unitOfWorkManage.BeginTran(); try { // 更新库存 var isUpdateStock = _billGroupStockRepository.UpdateNavStock(stock); // 添加历史任务 var isTaskHtyAdd = await _task_HtyRepository.AddDataAsync(taskHty) > 0; // 修改移库前货位状态 var isUpdateLoc = _locationRepository.UpdateData(locationInfo); // 删除任务数据 var isTaskDelete = await Delete(taskId); // 提交或回滚事务 if (isUpdateStock && isTaskHtyAdd && isTaskDelete && isUpdateLoc) { LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"事务处理完成,提交事务。添加历史任务:{isTaskHtyAdd},删除任务数据:{isTaskDelete},更新库存:{isUpdateStock},修改移库前货位状态:{isUpdateLoc}"); _unitOfWorkManage.CommitTran(); return true; } else { LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"数据处理失败,请检查数据是否正确,数据回滚。添加历史任务:{isTaskHtyAdd},删除任务数据:{isTaskDelete},更新库存:{isUpdateStock},修改移库前货位状态:{isUpdateLoc}"); _unitOfWorkManage.RollbackTran(); return false; } } catch (Exception err) { LogFactory.GetLog("任务完成").InfoFormat(true, $"移库任务完成,系统异常,异常信息:{err.Message}", "无参数"); _unitOfWorkManage.RollbackTran(); throw; // 抛出异常以便外部捕获 } } #endregion private 内部方法 }