using log4net.Core; using Mapster; using Masuit.Tools; using WIDESEA_DTO.MOM; using WIDESEA_DTO.WMS; using WIDESEA_IStorageBasicRepository; using WIDESEA_IStoragIntegrationServices; using WIDESEA_Model.Models; using WIDESEA_StorageBasicRepository; using WIDESEA_StorageTaskRepository; 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); var info = JsonConvert.DeserializeObject(process.ProcessValue); var agingOutputDto = MapToAgingOutputDto(stock, info); content = await _agingInOrOutInputService.GetOCVOutputAsync(agingOutputDto); ValidateResponse(content); } // 更新库存状态和任务状态 (var loc, var tas) = UpdateStockAndTaskStatus(stock, task); // 事务处理 await _unitOfWorkManage.UseTranAsync(async () => { await UpdateLocationAsync(loc); await DeleteStockInfoAsync(stock.Id); await DeleteStockInfoDetailsAsync(stock.StockInfoDetails); //await DeleteTaskAsync(task.TaskId); }); return content.OK("任务完成成功"); } catch (Exception err) { LogFactory.GetLog("任务完成").Error(true, $"系统异常,异常信息:{err.Message}"); return content.Error(err.Message); } } private AgingOutputDto MapToAgingOutputDto(DtStockInfo stock, ResponseEqptRunDto info) { return new AgingOutputDto { OpFlag = 1, Software = "WMS", EquipmentCode = "ECH001-B", TrayBarcode = stock.PalletCode, SerialNos = stock.StockInfoDetails.Select(x => new SerialNoOutDto { SlotNo = x.OrderNo.ToInt32(), SerialNo = x.SerialNumber, SerialNoResult = true, ParameterInfo = info.ParameterInfo.Select(x => new ParameterInfo() { LowerLomit = x.LowerControlLimit, UpperLimit = x.UpperControlLimit, ParameterResult = x.EquipmentAvailabilityFlag, ParameterCode = x.ParameterCode, ParameterDesc = x.Description, TargetValue = x.TargetValue, Value = (DateTime.Now - stock.CreateDate).TotalMinutes.ToString(), DefectCode = x.UOMCode }).ToList() }).ToList() }; } private void ValidateResponse(WebResponseContent content) { var result = JsonConvert.DeserializeObject(content.Data.ToString()); if (!result.Success) { throw new Exception(result.MOMMessage); } } private (DtLocationInfo, Dt_Task) UpdateStockAndTaskStatus(DtStockInfo stock, Dt_Task task) { var location = _locationRepository.QueryFirst(x => x.LocationCode == task.SourceAddress); var details = _stockInfoDetailRepository.QueryData(x => x.StockId == stock.Id); location.LocationStatus = (int)LocationEnum.Free; task.TaskState = (int)TaskOutStatusEnum.OutFinish; //task.CurrentAddress = task.NextAddress; //task.NextAddress = task.TargetAddress; LogFactory.GetLog("任务完成").Info(true, "更新库存状态与任务状态"); return (location, task); } private async Task DeleteStockInfoAsync(int stockId) { var isStockUpdated = await _stockInfoRepository.DeleteDataByIdAsync(stockId); if (!isStockUpdated) { throw new Exception("库存信息更新失败"); } } private async Task UpdateLocationAsync(DtLocationInfo info) { var isStockUpdated = await _locationRepository.UpdateDataAsync(info); if (!isStockUpdated) { throw new Exception("库存信息更新失败"); } } private async Task DeleteStockInfoDetailsAsync(IEnumerable details) { var ids = details.Select(x => (object)x.Id).ToArray(); var isStockDetailUpdated = await _stockInfoDetailRepository.DeleteDataByIdsAsync(ids); if (!isStockDetailUpdated) { throw new Exception("库存详情信息更新失败"); } } private async Task DeleteTaskAsync(int taskId) { var isTaskUpdated = await BaseDal.DeleteDataByIdAsync(taskId); if (!isTaskUpdated) { throw new Exception("任务信息更新失败"); } } #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 = boxing == null ? CreateEmptyPalletStock(task, locationInf) : CreateFullPalletStock(task, locationInf, boxing); // 执行数据库事务 bool isResult = await ExecuteTransaction(stock, taskHty, locationInf, task.TaskId); if (isResult) { content.OK("入库任务完成成功"); } else { content.Error("入库任务完成失败"); } } catch (Exception err) { // 记录异常信息到控制台和日志 Console.WriteLine(err.Message.ToString()); LogFactory.GetLog("任务完成").Error(true, err); } return content; } /// /// 创建空托盘的库存实例模型 /// private DtStockInfo CreateEmptyPalletStock(Dt_Task task, DtLocationInfo locationInf) { return new DtStockInfo() { PalletCode = task.PalletCode, LocationCode = task.TargetAddress, CreateDate = DateTime.Now, Creater = "system", IsFull = false, AreaCode = task.Roadway, StockInfoDetails = new List() { new DtStockInfoDetail() { MaterielCode = "空托盘", Id = 0, } } }; } /// /// 创建实盘的库存实例模型并调用MOM入库 /// private DtStockInfo CreateFullPalletStock(Dt_Task task, DtLocationInfo locationInf, DtBoxingInfo boxing) { var boxDetail = boxing.BoxingInfoDetails.Adapt>(); var stock = new DtStockInfo() { PalletCode = task.PalletCode, LocationCode = task.TargetAddress, CreateDate = DateTime.Now, Creater = "system", IsFull = boxing.IsFull, AreaCode = task.Roadway, 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, EquipmentCode = "ECH001-B", Software = "WMS" }; var result = _agingInOrOutInputService.GetOCVInputAsync(agingInputDto).Result; var respone = JsonConvert.DeserializeObject(result.Data.ToString()); stock.Remark = respone.LinedProcessFeedbackTime; // 记录日志 LogFactory.GetLog("任务完成").InfoFormat(true, "入库任务完成", $"货位地址:{task.TargetAddress},修改后货位数据:{locationInf}"); return stock; } #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.QueryFirstNavAsync(x => x.PalletCode == task.PalletCode); // 根据任务类型调用相应的完成任务方法 switch (task.TaskType) { case (int)TaskInboundTypeEnum.Inbound: case (int)TaskInboundTypeEnum.InTray: LogFactory.GetLog("任务完成").InfoFormat(true, "入库任务", ""); return await CompleteInboundTaskAsync(task); case (int)TaskOutboundTypeEnum.OutTray: case (int)TaskOutboundTypeEnum.Outbound: LogFactory.GetLog("任务完成").InfoFormat(true, "出库任务", ""); return await CompleteStackTaskAsync(task, stock); default: return content.Error("任务类型不存在"); } } #endregion 任务完成 #region 请求任务入库 /// /// 请求任务 /// /// 请求模型 /// 包含任务信息的响应内容 public async Task RequestTaskAsync(RequestTaskDto input) { // 创建一个WebResponseContent对象 WebResponseContent content = new WebResponseContent(); try { // 调用BaseDal.QueryFirstAsync方法,查询任务 var task = await BaseDal.QueryFirstAsync(x => x.PalletCode == input.PalletCode); if (task != null) { if (task.TaskState == (int)TaskInStatusEnum.InNew) { // 创建WMS任务 WMSTaskDTO taskDTO = new WMSTaskDTO() { TaskNum = task.TaskNum.Value, Grade = 1, PalletCode = task.PalletCode, RoadWay = task.Roadway, SourceAddress = task.SourceAddress, TargetAddress = task.Roadway, TaskState = task.TaskState.Value, Id = 0, TaskType = task.TaskType, }; return content.OK(data: taskDTO); } content = await UpdateExistingTask(input, task); return content; } // 创建一个TrayCellsStatusDto对象,并赋值 TrayCellsStatusDto trayCells = new TrayCellsStatusDto() { Software = "WMS", TrayBarcode = input.PalletCode, EquipmentCode = "ECH001-B" }; // 调用GetTrayCellStatusAsync方法,获取整盘电芯 content = await GetTrayCellStatusAsync(trayCells); // 如果状态为false,则返回content if (!content.Status) return content; // 添加组盘信息 // 将content.Data转换为ResultTrayCellsStatus对象 var result = JsonConvert.DeserializeObject(content.Data.ToString()); if (result.SerialNos.Count <= 0) return content.Error(result.MOMMessage); 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); // 如果task不为null,则调用UpdateExistingTask方法,更新任务;否则调用CreateNewTask方法,创建新任务 content = task != null ? await UpdateExistingTask(input, task) : await CreateNewTask(input, processResponse); 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; } public async Task RequestTrayInTaskAsync(RequestTaskDto input) { WebResponseContent content = new WebResponseContent(); try { // 调用BaseDal.QueryFirstAsync方法,查询任务 var task = await BaseDal.QueryFirstAsync(x => x.PalletCode == input.PalletCode); if (task != null && task.TaskState == (int)TaskInStatusEnum.InNew) { // 创建WMS任务 WMSTaskDTO taskDTO = new WMSTaskDTO() { TaskNum = task.TaskNum.Value, Grade = 1, PalletCode = task.PalletCode, RoadWay = task.Roadway, SourceAddress = task.SourceAddress, TargetAddress = task.Roadway, TaskState = task.TaskState.Value, Id = 0, TaskType = task.TaskType, }; return content.OK(data: task); } return await CreateNewTask(input, null, 1); } catch (Exception) { throw; } } // 获取托盘单元格状态 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 = serialNoObj.BindCode, Remark = result.TrayBarcodePropertys.ToJsonString(), }).ToList() }; } // 获取工艺申请 private async Task GetProcessApplyAsync(ResultTrayCellsStatus content) { // 创建一个ProcessApplyDto对象,并赋值 return new ProcessApplyDto() { EquipmentCode = "ECH001-B", Software = "WMS", //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 请求出库(实盘&空盘) /// /// 请求托盘任务 /// /// 目标位置 /// 托盘类型(1:实盘,2:空盘) /// 区域编码 /// 巷道编码集合 /// 返回结果集 public async Task RequestTrayOutTaskAsync(string position, int tag, string areaCode, List roadways) { WebResponseContent content = new WebResponseContent(); try { // 根据托盘类型查询库存信息 DtStockInfo stockInfo = tag == (int)TaskOutboundTypeEnum.Outbound ? QueryStockInfoForRealTray(areaCode, roadways) : QueryStockInfoForEmptyTray(areaCode, roadways); if (stockInfo == null) { return content.Error("库存信息不存在"); } // 创建新任务实例 var task = CreateTask(stockInfo, position, tag); var taskId = await BaseDal.AddDataAsync(task); bool isResult = taskId > 0; if (!isResult) { return content.Error("任务创建失败"); } // 创建任务DTO WMSTaskDTO taskDTO = CreateTaskDTO(task); //if (tag == 1) { // 更新库存位置状态为不可用 stockInfo.LocationInfo.LocationStatus = (int)LocationEnum.InStockDisable; await _locationRepository.UpdateDataAsync(stockInfo.LocationInfo); } // 返回成功响应 return content.OK(data: taskDTO); } catch (Exception ex) { // 记录异常信息并抛出 LogFactory.GetLog("请求托盘任务").Error(true, ex); return content.Error(ex.Message); } } /// /// 查询实盘库存信息 /// private DtStockInfo QueryStockInfoForRealTray(string areaCode, List roadways) { return _stockInfoRepository.Db.Queryable().Where(x => x.AreaCode == areaCode && Convert.ToDateTime(x.Remark) < DateTime.Now && x.LocationInfo.LocationStatus == (int)LocationEnum.InStock && roadways.Contains(x.LocationInfo.RoadwayNo)) .Includes(x => x.LocationInfo) .Includes(x => x.StockInfoDetails) .OrderBy(x => x.CreateDate) .First(); } /// /// 查询空盘库存信息 /// private DtStockInfo QueryStockInfoForEmptyTray(string areaCode, List roadways) { return _stockInfoRepository.Db.Queryable().Where(x => x.AreaCode == areaCode && x.StockInfoDetails.Any(z => z.MaterielCode == "空托盘") && roadways.Contains(x.LocationInfo.RoadwayNo)) .Includes(x => x.LocationInfo) .Includes(x => x.StockInfoDetails) .OrderBy(x => x.CreateDate) .First(); } /// /// 创建任务实例 /// private Dt_Task CreateTask(DtStockInfo stockInfo, string position, int tag) { return 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, CurrentAddress = stockInfo.LocationCode, TaskState = (int)TaskOutStatusEnum.OutNew, TaskType = tag == (int)TaskOutboundTypeEnum.Outbound ? (int)TaskOutboundTypeEnum.Outbound : (int)TaskOutboundTypeEnum.OutTray, TaskNum = BaseDal.GetTaskNo().Result, Creater = "System" // 修正拼写错误 }; } /// /// 创建任务DTO /// private WMSTaskDTO CreateTaskDTO(Dt_Task task) { return new WMSTaskDTO { TaskNum = task.TaskNum.Value, Grade = 1, PalletCode = task.PalletCode, RoadWay = task.Roadway, SourceAddress = task.SourceAddress, TargetAddress = task.TargetAddress, TaskState = task.TaskState.Value, Id = 0, TaskType = task.TaskType, }; } #endregion 请求出库 #region 任务状态更改 public async Task UpdateTaskStatus(int taskNum, int taskState) { WebResponseContent content = new WebResponseContent(); try { var task = await BaseDal.QueryFirstAsync(x => x.TaskNum == taskNum); if (task == null) return content.Error("未找到任务"); task.TaskState = taskState; var asb = await BaseDal.UpdateDataAsync(task); if (asb) content.OK(); else content.Error(); } catch (Exception ex) { content.Error(ex.Message); } 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(RequestTaskDto input, List process = null, int flag = 0) { WebResponseContent content = new WebResponseContent(); List strings = new List(); if (process != null) { strings = process.Select(x => x.EquipmentName).ToList(); } else { strings = input.Position.Split(',').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 = flag == 0 ? (int)TaskInboundTypeEnum.Inbound : (int)TaskInboundTypeEnum.InTray, 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 = task.TaskNum.Value, Grade = 1, PalletCode = task.PalletCode, RoadWay = task.Roadway, SourceAddress = task.SourceAddress, TargetAddress = task.Roadway, TaskState = task.TaskState.Value, Id = 0, TaskType = task.TaskType, }; 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) .OrderByDescending(g => g.Count()) // 根据每个组的元素数量排序 .First(); // 取出数量最多的组 string minRoadwayNo = minGroup.Key; // 数量最多的组的Key return minRoadwayNo; } /// /// 获取巷道或站台 /// /// public async Task GetRoadWayAsync(int areaCode) { var minGroup = _locationRepository.QueryData(x => x.AreaId == areaCode && x.LocationStatus == (int)LocationEnum.Free) .GroupBy(x => x.RoadwayNo) .OrderBy(g => g.Count()) // 根据每个组的元素数量排序 .First(); // 取出数量最少的组 string minRoadwayNo = minGroup.Key; // 数量最少的组的Key return minRoadwayNo; } #endregion 任务请求方法 #endregion private 内部方法 }