using Mapster; using Masuit.Tools; using WIDESEA_DTO.MOM; using WIDESEA_DTO.WMS; using WIDESEA_IStorageBasicRepository; using WIDESEA_IStoragIntegrationServices; using WIDESEA_StorageBasicRepository; using WIDESEA_StoragIntegrationServices; 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 IStockInfoRepository _stockInfoRepository; private readonly IStockInfoDetailRepository _stockInfoDetailRepository; 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 ILocationInfoRepository _locationRepository; private readonly IDt_WareAreaInfoRepository _wareAreaInfoRepository; private readonly IPointStackerRelationRepository _pointStackerRelationRepository; private readonly ITaskExecuteDetailRepository _taskExecuteDetailRepository; private readonly ILocationStatusChangeRecordRepository _locationStatusChangeRecordRepository; private readonly IBoxingInfoRepository _boxingInfoRepository; //组盘 private readonly ICellStateService _cellStateService; //电芯属性 private readonly IProcessApplyService _processApplyService; //工艺路线 private readonly IDt_AreaInfoRepository _areaInfoRepository; //区域 private readonly IAgingInOrOutInputService _agingInOrOutInputService; //静置\陈化 public Dt_TaskService(IDt_TaskRepository BaseDal, IUnitOfWorkManage unitOfWorkManage, IDt_OutOrderRepository outOrderRepository, IStockInfoRepository stockInfoRepository, IDt_OutOrderAndStockRepository dt_OutOrderAndStockRepository, IDt_OutOrderAndStock_HtyRepository dt_OutOrderAndStock_HtyRepository, IDt_Task_HtyRepository task_HtyRepository, IMapper mapper, IDt_MaterielInfoRepository materielInfoRepository, ILocationInfoRepository locationRepository, IDt_WareAreaInfoRepository wareAreaInfoRepository, IPointStackerRelationRepository pointStackerRelationRepository, ITaskExecuteDetailRepository taskExecuteDetailRepository, ILocationStatusChangeRecordRepository locationStatusChangeRecordRepository, IBoxingInfoRepository boxingInfoRepository, ICellStateService cellStateService, IProcessApplyService processApplyService, IDt_AreaInfoRepository areaInfoRepository, IAgingInOrOutInputService agingInOrOutInputService, IStockInfoDetailRepository stockInfoDetailRepository) : base(BaseDal) { _unitOfWorkManage = unitOfWorkManage; _outOrderRepository = outOrderRepository; _stockInfoRepository = stockInfoRepository; _outOrderAndStockRepository = dt_OutOrderAndStockRepository; _outOrderAndStock_HtyRepository = dt_OutOrderAndStock_HtyRepository; _task_HtyRepository = task_HtyRepository; _mapper = mapper; _materielInfoRepository = materielInfoRepository; _locationRepository = locationRepository; _wareAreaInfoRepository = wareAreaInfoRepository; _pointStackerRelationRepository = pointStackerRelationRepository; _taskExecuteDetailRepository = taskExecuteDetailRepository; _locationStatusChangeRecordRepository = locationStatusChangeRecordRepository; _boxingInfoRepository = boxingInfoRepository; _cellStateService = cellStateService; _processApplyService = processApplyService; _areaInfoRepository = areaInfoRepository; _agingInOrOutInputService = agingInOrOutInputService; _stockInfoDetailRepository = stockInfoDetailRepository; } #region 外部接口方法 #region 出库任务完成 /// /// 出库任务完成 /// /// 任务数据合集 /// 返回结果集 public async Task CompleteStackTaskAsync(Dt_Task task, DtStockInfo stock) { WebResponseContent content = new WebResponseContent(); try { if (task.TaskType == (int)TaskOutboundTypeEnum.Outbound) { var process = await SqlSugarHelper.Db.Queryable() .FirstAsync(x => x.EquipmentName == task.Roadway); EquipmentParameterInfo info = JsonConvert.DeserializeObject(process.ProcessValue); AgingOutputDto agingOutputDto = new AgingOutputDto() { OpFlag = 1, EquipmentCode = stock.LocationInfo.RoadwayNo, TrayBarcode = stock.PalletCode, SerialNos = stock.StockInfoDetails.Select(x => new SerialNoOutDto() { SlotNo = x.OrderNo.ToInt32(), SerialNo = x.SerialNumber, SerialNoResult = true, ParameterInfo = new List() { new ParameterInfo() { LowerLomit =info.LowerControlLimit, UpperLimit = info.UpperControlLimit, ParameterResult = info.EquipmentAvailabilityFlag, ParameterCode = info.ParameterCode, ParameterDesc = info.Description, TargetValue = info.TargetValue, Value = info.TargetValue, DefectCode = info.UOMCode } } }).ToList() }; } // 更新库存状态 var loation = _locationRepository.QueryFirst(x => x.LocationCode == task.SourceAddress); var detail = _stockInfoDetailRepository.QueryData(x => x.StockId == stock.Id); // 设置库位状态为空闲 loation.LocationStatus = LocationEnum.Free.ObjToInt(); // 更新任务状态 task.TaskState = TaskOutStatusEnum.OutFinish.ObjToInt(); task.CurrentAddress = task.NextAddress; task.NextAddress = task.TargetAddress; LogFactory.GetLog("任务完成").InfoFormat(true, "堆垛机出库完成", "更新库存状态与任务状态"); // 事务处理 // 开始事务 _unitOfWorkManage.BeginTran(); // 删除库存信息 var isStockUpdated = _stockInfoRepository.DeleteDataById(stock.Id); // 删除库存信息 var isStockDetailUpdated = _stockInfoDetailRepository.DeleteDataByIds(detail.Select(x => (object)x.Id).ToArray()); // 删除任务信息 var isTaskUpdated = BaseDal.DeleteDataById(task.TaskId); // 如果库存信息和任务信息都更新成功 if (isStockUpdated && isTaskUpdated && isStockDetailUpdated) { // 记录日志 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); } } #endregion 堆垛机出库任务完成 #region 移库任务完成 /// /// 移库任务完成 /// /// 任务数据合集 /// 返回结果集 public async Task CompleteTransferTaskAsync(Dt_Task task, DtStockInfo stock) { WebResponseContent content = new WebResponseContent(); try { // 更新货位和库存信息 (DtStockInfo updateStock, DtLocationInfo locationInf) = UpdateStockLocation(stock, task.NextAddress); var taskHty = CreateHistoricalTask(task); LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"货位地址:{task.TargetAddress},修改后库存数据:{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; } #endregion 移库任务完成 #region 入库任务完成 /// /// 入库任务完成 /// /// 任务数据合集 /// 返回结果集 public async Task CompleteInboundTaskAsync(Dt_Task task) { WebResponseContent content = new WebResponseContent(); try { var boxing = await _boxingInfoRepository.QueryFirstNavAsync(x => x.PalletCode == task.PalletCode); var locationInf = await _locationRepository.QueryFirstAsync(x => x.LocationCode == task.TargetAddress); locationInf.LocationStatus = (int)LocationEnum.InStock; // 创建历史任务实例模型 var taskHty = CreateHistoricalTask(task); // 创建库存实例模型 DtStockInfo stock; if (boxing == null) { // 空托盘 stock = new DtStockInfo() { PalletCode = task.PalletCode, LocationCode = task.TargetAddress, CreateDate = DateTime.Now, Creater = "system", IsFull = boxing.IsFull, StockInfoDetails = new List() { new DtStockInfoDetail() { MaterielCode = "空托盘", Id = 0, } } }; } else { // 实盘 var boxDetail = boxing.BoxingInfoDetails.Adapt>(); // 创建库存实例模型 stock = new DtStockInfo() { PalletCode = task.PalletCode, LocationCode = task.TargetAddress, CreateDate = DateTime.Now, Creater = "system", IsFull = boxing.IsFull, StockInfoDetails = boxDetail, }; AgingInputDto agingInputDto = new AgingInputDto() { SerialNos = boxing.BoxingInfoDetails .Select(item => new SerialNoInDto { SerialNo = item.SerialNumber, PositionNo = item.OrderNo }) .ToList(), TrayBarcode = task.PalletCode, OpFlag = 1 }; var result = await _agingInOrOutInputService.GetOCVInputAsync(agingInputDto); stock.Remark = JsonConvert.DeserializeObject(result.Data.ToString()).LinedProcessFeedbackTime; LogFactory.GetLog("任务完成").InfoFormat(true, "入库任务完成", $"货位地址:{task.TargetAddress},修改后货位数据:{locationInf}"); } // 执行数据库事务 bool isResult = await ExecuteTransaction(stock, taskHty, locationInf, task.TaskId); if (isResult) content.OK("入库任务完成成功"); else content.Error("入库任务完成失败"); } catch (Exception err) { Console.WriteLine(err.Message.ToString()); } return content; } #endregion 入库任务完成 #region 任务完成 /// /// 任务完成 /// /// 任务号 /// 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 _stockInfoRepository.QueryFirstAsync(x => x.PalletCode == task.PalletCode); if (stock == null) { LogFactory.GetLog("任务完成").InfoFormat(true, "库存不存在存在,判断是否是入库任务", $"{task.TaskType}"); if (task.TaskType == (int)TaskInboundTypeEnum.Inbound) { LogFactory.GetLog("任务完成").InfoFormat(true, "入库任务", ""); return await CompleteInboundTaskAsync(task); } else if (task.TaskType == (int)TaskInboundTypeEnum.InTray) { LogFactory.GetLog("任务完成").InfoFormat(true, "空托盘入库", ""); return await CompleteInboundTaskAsync(task); } else { LogFactory.GetLog("任务完成").InfoFormat(true, "任务状态异常", ""); return content.Error("任务状态异常"); } } LogFactory.GetLog("任务完成").InfoFormat(true, "验证库存是否存在", JsonConvert.SerializeObject(stock)); if (task.TaskType == (int)TaskOutboundTypeEnum.Outbound) { LogFactory.GetLog("任务完成").InfoFormat(true, "出库任务", ""); if (task.TaskState == TaskOutStatusEnum.Line_OutFinish.ObjToInt()) { LogFactory.GetLog("任务完成").InfoFormat(true, "堆垛机出库完成", ""); return await CompleteStackTaskAsync(task, stock); } else if (task.TaskState == TaskOutStatusEnum.SC_OutExecuting.ObjToInt()) { LogFactory.GetLog("任务完成").InfoFormat(true, "库存不存在也不是入库任务", ""); return content.Error("库存不存在"); } else { LogFactory.GetLog("任务完成").InfoFormat(true, "任务状态异常", ""); return content.Error("任务状态异常"); } } 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 RequestTaskAsync(RequestTaskDto input) { // 创建一个WebResponseContent对象 WebResponseContent content = new WebResponseContent(); try { // 创建一个TrayCellsStatusDto对象,并赋值 TrayCellsStatusDto trayCells = new TrayCellsStatusDto() { TrayBarcode = input.PalletCode }; // 调用GetTrayCellStatusAsync方法,获取整盘电芯 content = await GetTrayCellStatusAsync(trayCells); // 如果状态为false,则返回content if (!content.Status) return content; // 添加组盘信息 // 将content.Data转换为ResultTrayCellsStatus对象 var result = JsonConvert.DeserializeObject(content.ToString()); var boxing = await CreateBoxingInfo(result, input.PalletCode); // 调用GetProcessApplyAsync方法,获取工艺路线 ProcessApplyDto process = await GetProcessApplyAsync(result); // 如果process为null,则返回content if (process == null) return content; // 调用GetProcessResponseAsync方法,获取工艺响应 var processResponse = await GetProcessResponseAsync(process, input.Position); // 调用BaseDal.QueryFirstAsync方法,查询任务 var task = await BaseDal.QueryFirstAsync(x => x.PalletCode == input.PalletCode); // 如果task不为null,则调用UpdateExistingTask方法,更新任务;否则调用CreateNewTask方法,创建新任务 content = task != null ? await UpdateExistingTask(input, task) : await CreateNewTask(processResponse, input); if (content.Status) { var isBox = await _boxingInfoRepository.AddDataNavAsync(boxing); } } catch (Exception err) { // 如果发生异常,则调用content.Error方法,记录错误信息,并输出错误信息 content.Error(err.Message); Console.WriteLine(err.Message); } // 返回content return content; } // 获取托盘单元格状态 private async Task GetTrayCellStatusAsync(TrayCellsStatusDto trayCells) { // 调用_cellStateService.GetTrayCellStatusAsync方法,获取托盘单元格状态 return await _cellStateService.GetTrayCellStatusAsync(trayCells); } // 获取组盘信息 private async Task CreateBoxingInfo(ResultTrayCellsStatus result, string palletCode) { return new DtBoxingInfo { PalletCode = palletCode, IsFull = true, BoxingInfoDetails = result.SerialNos.Select(serialNoObj => new DtBoxingInfoDetail { SerialNumber = serialNoObj.SerialNo, OrderNo = serialNoObj.PositionNo.ToString(), Status = serialNoObj.SerialNoStatus, MaterielCode = result.BindCode, Remark = result.TrayBarcodePropertys.ToJsonString(), }).ToList() }; } // 获取工艺申请 private async Task GetProcessApplyAsync(ResultTrayCellsStatus content) { // 创建一个ProcessApplyDto对象,并赋值 return new ProcessApplyDto() { //WipOrderNo = result.BindCode, SerialNos = content.SerialNos.Select(item => new SerialNos { SerialNo = item.SerialNo }).ToList() }; } // 获取工艺响应 private async Task> GetProcessResponseAsync(ProcessApplyDto process, string position) { // 如果process为null,则返回null if (process == null) return null; // 调用_processApplyService.GetProcessApplyAsync方法,获取工艺申请 WebResponseContent content = await _processApplyService.GetProcessApplyAsync(process); // 如果状态为false,则返回null if (!content.Status) return null; // 将content.Data转换为ResultProcessApply对象 var apply = JsonConvert.DeserializeObject(content.Data.ToString()); // 根据position的值,返回不同的Dt_EquipmentProcess列表 switch (position) { case "1088": return SqlSugarHelper.Db.Queryable() .Where(x => x.EquipmentType == "陈化" && x.WipOrderNo == apply.WipOrderNo && x.ProductDesc == apply.ProductNo) .ToList(); case "1339": case "1406": return SqlSugarHelper.Db.Queryable() .Where(x => x.EquipmentType == "静置" && x.WipOrderNo == apply.WipOrderNo && x.ProductDesc == apply.ProductNo) .ToList(); default: return new List(); } } #endregion 请求任务 #region 请求空托盘 public async Task RequestTrayTaskAsync(string position) { WebResponseContent content = new WebResponseContent(); try { var area = _areaInfoRepository.QueryFirst(x => x.AreaCode == "CH"); var stockInfo = _stockInfoRepository.QueryData(x => x.LocationInfo.AreaId == area.AreaID && x.StockInfoDetails.Any(z => z.MaterielCode == "空托盘")).OrderBy(x => x.CreateDate).FirstOrDefault(); // 创建新任务实例 var task = new Dt_Task { CurrentAddress = stockInfo.LocationCode, Grade = 1, Roadway = stockInfo.LocationInfo.RoadwayNo, TargetAddress = position, Dispatchertime = DateTime.Now, MaterialNo = "", NextAddress = position, OrderNo = null, PalletCode = stockInfo.PalletCode, SourceAddress = stockInfo.LocationCode, TaskState = (int)TaskOutStatusEnum.OutNew, TaskType = (int)TaskOutboundTypeEnum.OutTray, TaskNum = await BaseDal.GetTaskNo(), Creater = "Systeam" }; var taskId = await BaseDal.AddDataAsync(task); bool isResult = taskId > 0; if (isResult) { WMSTaskDTO taskDTO = new WMSTaskDTO() { TaskNum = task.TaskNum.Value, Grade = 1, PalletCode = DateTime.Now.ToString("MMddHHmmss"), RoadWay = task.Roadway, SourceAddress = stockInfo.LocationCode, TargetAddress = task.Roadway, TaskState = (int)TaskOutStatusEnum.OutNew, Id = 0, TaskType = (int)TaskOutboundTypeEnum.OutTray }; content.OK(data: taskDTO); } } catch (Exception ex) { throw; } return content; } #endregion 请求空托盘 #region 陈化请求出库 // 陈化请求出库 public async Task OutTrayByCh(string position) { WebResponseContent content = new WebResponseContent(); try { var area = _areaInfoRepository.QueryFirst(x => x.AreaName == "陈化区"); // 查询库存信息 var stockInfo = _stockInfoRepository.QueryData(x => x.AreaCode == area.AreaCode && Convert.ToDateTime(x.Remark) < DateTime.Now && x.LocationInfo.LocationStatus == (int)LocationEnum.InStock).OrderBy(x => x.CreateDate).FirstOrDefault(); // 创建新任务实例 var task = new Dt_Task() { Grade = 1, Roadway = stockInfo.LocationInfo.RoadwayNo, TargetAddress = position, Dispatchertime = DateTime.Now, MaterialNo = "", NextAddress = position, OrderNo = null, PalletCode = stockInfo.PalletCode, SourceAddress = stockInfo.LocationCode, TaskState = (int)TaskOutStatusEnum.OutNew, TaskType = (int)TaskOutboundTypeEnum.OutTray, TaskNum = await BaseDal.GetTaskNo(), Creater = "Systeam" }; var taskId = await BaseDal.AddDataAsync(task); bool isResult = taskId > 0; if (isResult) { WMSTaskDTO taskDTO = new WMSTaskDTO() { TaskNum = task.TaskNum.Value, Grade = 1, PalletCode = DateTime.Now.ToString("MMddHHmmss"), RoadWay = task.Roadway, SourceAddress = stockInfo.LocationCode, TargetAddress = task.Roadway, TaskState = (int)TaskOutStatusEnum.OutNew, Id = 0, TaskType = (int)TaskOutboundTypeEnum.OutTray }; stockInfo.LocationInfo.LocationStatus = (int)LocationEnum.InStockDisable; _locationRepository.UpdateData(stockInfo.LocationInfo); content.OK(data: taskDTO); } } catch (Exception ex) { throw; } return content; } #endregion 陈化请求出库 #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(DtStockInfo stock, string barCode) { //根据PalletCode获取订单和库存信息 var orderStock = await _outOrderAndStockRepository.GetOrderAndStock(palletCode: barCode); //完成数量增加 orderStock.CompletedQuantity += stock.StockInfoDetails.Sum(x => x.StockQuantity); //订单详情完成数量增加 orderStock.OrderList.OrderDetailList.CompletedQuantity += stock.StockInfoDetails.Sum(x => x.StockQuantity); //返回更新后的订单和库存信息 return orderStock; } /// /// 判断订单是否完成 /// /// 订单和库存信息 /// 是否完成 // 判断订单是否完成 private bool IsOrderComplete(Dt_OutOrderAndStock orderStock) { // 如果出库数量等于完成出库数量,则订单完成 return orderStock.CompletedQuantity == orderStock.OutboundQuantity; } /// /// 创建历史任务记录 /// /// /// private Dt_Task_Hty CreateHistoricalTask(Dt_Task task) { // 更新任务状态 task.TaskState = TaskOutStatusEnum.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 = TaskOutStatusEnum.OutFinish.ObjToInt(); return taskHty; } /// /// 更新库存位置 /// /// 库存对象 /// 目标位置 // 更新库存和位置信息 private (DtStockInfo, DtLocationInfo) UpdateStockLocation(DtStockInfo stock, string toLocation) { // 获取库存信息 var locationInfo = _locationRepository.QueryFirst(x => x.LocationCode == stock.LocationCode); // 将库存状态设置为在库 locationInfo.LocationStatus = LocationEnum.InStock.ObjToInt(); // 将库存位置设置为目标位置 stock.LocationCode = toLocation; // 将库存状态设置为在库 stock.LocationInfo.LocationStatus = LocationEnum.InStock.ObjToInt(); // 返回更新后的库存和位置信息 return (stock, locationInfo); } /// /// 执行数据库事务 /// /// 库存对象 /// 历史任务对象 /// 任务ID /// private async Task ExecuteTransaction(DtStockInfo stock, Dt_Task_Hty taskHty, DtLocationInfo locationInfo, int taskId) { _unitOfWorkManage.BeginTran(); try { var isUpdateStock = true; if (taskHty.TaskType == (int)TaskTypeEnum.Outbound) { // 更新库存 isUpdateStock = await _stockInfoRepository.UpdateDataAsync(stock); } else { // 添加库存 isUpdateStock = await _stockInfoRepository.AddDataNavAsync(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; // 抛出异常以便外部捕获 } } #region 任务请求方法 /// /// 更新现有任务 /// /// 请求模型 /// 区域ID /// 任务实例 /// 响应内容 /// private async Task UpdateExistingTask(RequestTaskDto input, Dt_Task task) { // 创建WebResponseContent对象 WebResponseContent content = new WebResponseContent(); // 定义变量 string toAddress; int taskState; string original = task.CurrentAddress; DtLocationInfo location = new DtLocationInfo(); int beforeStatus = 0; // 处理入库任务 location = await GetLocationDistributeAsync(task.Roadway); toAddress = location.LocationCode; taskState = (int)TaskInStatusEnum.Line_InFinish; beforeStatus = location.LocationStatus; // 更新货位信息 location.LocationStatus = (int)LocationEnum.Lock; // 更新任务信息 task.CurrentAddress = input.Position; task.TargetAddress = toAddress; task.NextAddress = toAddress; task.TaskState = taskState; // 开始事务 _unitOfWorkManage.BeginTran(); // 定义变量 bool isUpdateLo = true; bool isUpdateChange = true; // 尝试更新任务 bool isResult = await BaseDal.UpdateDataAsync(task); bool isTaskDetail = await _taskExecuteDetailRepository.AddDetailAsync(task, false, TaskDescription.GetTaskUpdateDescription(task.PalletCode, original, input.Position, TaskInStatusEnum.Line_InFinish.GetIntegralRuleTypeEnumDesc())); // 创建LocationChangeRecordDto对象 LocationChangeRecordDto changeRecordDto = new LocationChangeRecordDto() { // 设置变量 AfterStatus = location.LocationStatus, BeforeStatus = beforeStatus, TaskNum = task.TaskNum.Value, LocationId = location.Id, LocationCode = location.LocationCode, ChangeType = (int)StatusChangeTypeEnum.AutomaticStorage, }; // 更新位置状态 isUpdateChange = _locationStatusChangeRecordRepository.AddStatusChangeRecord(changeRecordDto); isUpdateLo = await _locationRepository.UpdateDataAsync(location); if (isResult && isUpdateLo && isTaskDetail) { // 提交事务 _unitOfWorkManage.CommitTran(); content.OK(data: task); } else { // 回滚事务 _unitOfWorkManage.RollbackTran(); content.Error("更新任务失败"); } return content; } /// /// 创建新任务 /// /// 请求模型 /// 区域ID /// 响应内容 /// private async Task CreateNewTask(List process, RequestTaskDto input) { WebResponseContent content = new WebResponseContent(); List strings = process.Select(x => x.EquipmentName).ToList(); // 获取目标地址 string ToAddress = await GetRoadWayAsync(strings); // 创建新任务实例 var task = new Dt_Task { CurrentAddress = input.Position, Grade = 1, Roadway = ToAddress, TargetAddress = ToAddress, Dispatchertime = DateTime.Now, MaterialNo = "", NextAddress = ToAddress, OrderNo = null, PalletCode = input.PalletCode, SourceAddress = input.Position, TaskState = (int)TaskInStatusEnum.InNew, TaskType = (int)TaskTypeEnum.Inbound, TaskNum = await BaseDal.GetTaskNo(), Creater = "Systeam" }; // 尝试添加新任务 var taskId = await BaseDal.AddDataAsync(task); bool isResult = taskId > 0; if (isResult) { task.TaskId = taskId; isResult = await _taskExecuteDetailRepository.AddDetailAsync(task, false, TaskDescription.GetTaskUpdateDescription(input.PalletCode, input.Position, ToAddress, TaskInStatusEnum.InNew.GetIntegralRuleTypeEnumDesc())); if (isResult) { // 创建WMS任务 WMSTaskDTO taskDTO = new WMSTaskDTO() { TaskNum = 0, Grade = 1, PalletCode = DateTime.Now.ToString("MMddHHmmss"), RoadWay = task.Roadway, SourceAddress = input.Position, TargetAddress = task.Roadway, TaskState = (int)TaskInStatusEnum.InNew, Id = 0, TaskType = (int)TaskInboundTypeEnum.Inbound, }; content.OK(data: taskDTO); } else content.Error("添加任务失败"); } else content.Error("添加任务失败"); return content; } /// /// 查找货位 /// /// 区域主键 /// 巷道 /// public async Task GetLocationDistributeAsync(string roadWay) { #region 获取货位 try { var locations = await _locationRepository.QueryDataAsync(x => x.LocationStatus == (int)LocationEnum.Free && x.RoadwayNo == roadWay); if (locations == null) { return null; } return locations.OrderBy(x => x.Layer).ThenBy(x => x.Column).ThenBy(x => x.Row).FirstOrDefault(); } catch (Exception err) { Console.WriteLine(err.Message.ToString()); return null; } #endregion 获取货位 } /// /// 获取巷道或站台 /// /// 货位区域ID /// 站台 /// 方向 /// 关系区域 /// public async Task GetRoadWayAsync(List process) { var minGroup = _locationRepository.QueryData(x => process.Contains(x.RoadwayNo) && x.LocationStatus == (int)LocationEnum.Free) .GroupBy(x => x.RoadwayNo) .OrderBy(g => g.Count()) // 根据每个组的元素数量排序 .First(); // 取出数量最少的组 string minRoadwayNo = minGroup.Key; // 数量最少的组的Key return minRoadwayNo; } #endregion 任务请求方法 #endregion private 内部方法 }