using AngleSharp.Dom; using COSXML.Network; using DocumentFormat.OpenXml.Drawing.Charts; using DocumentFormat.OpenXml.Math; using Elastic.Clients.Elasticsearch.Tasks; using Furion.DatabaseAccessor; using Furion.Logging; using Microsoft.AspNetCore.SignalR; using NewLife; using WCS.Application.Entity; using WCS.Application.Service.WcsTask.Dto; using WCS.Application.Util; namespace WCS.Application; /// /// 任务表服务 /// [ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)] public class WcsTaskService : IDynamicApiController, ITransient { private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId); private readonly SqlSugarRepository _wcsTaskRep; private readonly IHubContext _taskLogHubContext; private readonly SqlSugarRepository _wcsCheckTaskRep; private readonly SqlSugarRepository _wcsMateialPzInfoRep; public WcsTaskService(SqlSugarRepository wcsTaskRep, IHubContext taskLogHubContext, SqlSugarRepository wcsCheckTaskRep, SqlSugarRepository wcsMateialPzInfoRep) { _wcsTaskRep = wcsTaskRep; _taskLogHubContext = taskLogHubContext; _wcsCheckTaskRep = wcsCheckTaskRep; _wcsMateialPzInfoRep = wcsMateialPzInfoRep; } /// /// 分页查询任务表 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Page")] [DisplayName("分页查询任务表")] public async Task> Page(PageWcsTaskInput input) { input.SearchKey = input.SearchKey?.Trim(); var query = _wcsTaskRep.AsQueryable() .WhereIF(!string.IsNullOrEmpty(input.SearchKey), u => u.TaskNo.Contains(input.SearchKey) ) .WhereIF(!string.IsNullOrWhiteSpace(input.TaskNo), u => u.TaskNo.Contains(input.TaskNo.Trim())) .WhereIF(input.TaskType.HasValue, u => u.TaskType == input.TaskType) .WhereIF(input.Status.HasValue, u => u.Status == input.Status) .WhereIF(!string.IsNullOrWhiteSpace(input.PalletNo), u => u.PalletNo.Contains(input.PalletNo.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.Origin), u => u.Origin.Contains(input.Origin.Trim())) .Select(); return await query.OrderByDescending(o => o.Id) .ToPagedListAsync(input.Page, input.PageSize); } /// /// 增加任务表 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Add")] [DisplayName("增加任务表")] public async Task Add(AddWcsTaskInput input) { if (await _wcsTaskRep.AsQueryable().AnyAsync(s => s.TaskNo == input.TaskNo)) { throw Oops.Bah("任务号重复"); } if (input.UnstackingMode == UnstackingModeEnum.Machine) { if (string.IsNullOrEmpty(input.SkuNo) || string.IsNullOrEmpty(input.SkuName)) { throw Oops.Bah("机器人拣货,物料和批次信息不能为空"); } } var entity = input.Adapt(); entity.Origin = "WCS"; if (string.IsNullOrEmpty(entity.TaskNo)) { //生成任务号 entity.TaskNo = GetTaskCode(); // 判断是否穿梭车任务 if (entity.Type != PLCTypeEnum.AGV) { entity.TaskId = FourWayCarUtil.GetTaskId(); } if (string.IsNullOrEmpty(entity.TaskNo)) { throw Oops.Bah("任务号生成失败"); } } #region 机器人拆垛分配拆垛工位 if (entity.UnstackingMode == UnstackingModeEnum.Machine) { //分拣任务信息 List taskPortList = await _wcsCheckTaskRep.Context.Queryable().Where(w => w.RoboatType == PLCTypeEnum.StackingRobot).Select().ToListAsync(); if (taskPortList.Count <= 0) { throw Oops.Bah("拆垛工位异常"); } var taskList = await _wcsTaskRep.Context.Queryable().Where(w => w.Status == 0 && w.IsBind == 0 && w.TaskType == TaskTypeEnum.Out).ToListAsync(); foreach (var item in taskPortList) { item.PortCount = taskList.Where(w => w.StationNum == item.Port).Count(); } var portInfo = taskPortList.OrderBy(o => o.PortCount).ThenBy(o => o.LineNO).First(); //拆垛工位号 entity.StationNum = portInfo.Port; } #endregion await _wcsTaskRep.InsertAsync(entity); return entity.Id; } /// /// 删除任务表 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Delete")] [DisplayName("删除任务表")] public async Task Delete(DeleteWcsTaskInput input) { var entity = await _wcsTaskRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002); await _wcsTaskRep.FakeDeleteAsync(entity); //假删除 //await _wcsTaskRep.DeleteAsync(entity); //真删除 } /// /// 更新任务表 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Update")] [DisplayName("更新任务表")] public async Task Update(UpdateWcsTaskInput input) { var entity = input.Adapt(); await _wcsTaskRep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } /// /// 获取任务表 /// /// /// [HttpGet] [ApiDescriptionSettings(Name = "Detail")] [DisplayName("获取任务表")] public async Task Detail([FromQuery] QueryByIdWcsTaskInput input) { return await _wcsTaskRep.GetFirstAsync(u => u.Id == input.Id); } /// /// 获取任务表列表 /// /// /// [HttpGet] [ApiDescriptionSettings(Name = "List")] [DisplayName("获取任务表列表")] public async Task> List([FromQuery] PageWcsTaskInput input) { return await _wcsTaskRep.AsQueryable().Select().ToListAsync(); } /// /// 完成/取消任务表 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Finsh")] [DisplayName("完成/取消任务表")] [UnitOfWork] public async Task Finsh(UpdateWcsTaskInput input) { if (input.Status == TaskStatusEnum.Complete || input.Status == TaskStatusEnum.Cancell) { var modTask = await _wcsTaskRep.GetByIdAsync(input.Id); if (modTask.Status > TaskStatusEnum.Doing) throw Oops.Oh("任务状态异常"); if (input.Type == PLCTypeEnum.AGV) PLCService.AGVStatus = false; if (input.Status == TaskStatusEnum.Cancell && input.Type == PLCTypeEnum.AGV && modTask.Status == TaskStatusEnum.Doing) { CancelTaskModel model = new CancelTaskModel() { ReqCode = Guid.NewGuid().ToString("N"), TaskCode = modTask.TaskNo, ReqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), ForceCancel = "0" }; var response = new HttpService().CancelTask(model).Result; if (response.code == "0") { WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = 0, PlcName = "", Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, InteractiveMsg = "任务已手动取消", PalletNo = modTask.PalletNo }; await _wcsTaskRep.Context.Insertable(modTaskMonitor).ExecuteCommandAsync(); HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt()); } return; } else { if (input.Status == TaskStatusEnum.Complete) { modTask.IsSuccess = TaskSuccessEnum.Success; modTask.FinishDate = DateTime.Now;//完成时间 } else { modTask.IsSuccess = TaskSuccessEnum.Fail; modTask.CancelDate = DateTime.Now;//取消时间 } modTask.Status = input.Status; modTask.Levels = 999; await _wcsTaskRep.Context.Updateable(modTask).UpdateColumns(s => new { s.Status, s.IsSuccess, s.FinishDate, s.CancelDate, s.UpdateTime, s.UpdateUserId, s.UpdateUserName }).ExecuteCommandAsync(); //写入任务明细表 WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = 0, PlcName = "", Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, InteractiveMsg = input.Status == TaskStatusEnum.Complete ? "任务已手动完成" : "任务已手动取消", PalletNo = modTask.PalletNo }; await _wcsTaskRep.Context.Insertable(modTaskMonitor).ExecuteCommandAsync(); HubUtil.PublicTask(modTask.Adapt()); HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt()); } } else { throw Oops.Oh("任务状态异常"); } } // /// 手动给WMS上传任务 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "UploadTask")] [DisplayName("手动给WMS上传任务")] public async Task UploadTask(UpdateWcsTaskInput input) { var modTask = await _wcsTaskRep.GetByIdAsync(input.Id); if (modTask.Status != TaskStatusEnum.Complete) { throw Oops.Oh("任务状态异常"); } if (modTask.Origin != "WMS") { throw Oops.Oh("该任务来源不是WMS"); } // 反馈WMS var requestMode = new TaskRequestWMS() { TaskNo = modTask.TaskNo, PalletNo = modTask.PalletNo, TaskType = ((int)modTask.TaskType).ToString(), TaskStatus = ((int)TaskStatusEnum.Complete).ToString() }; //任务详情 var modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = 0, PlcName = "", PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, InteractiveMsg = $"手动上传给WMS任务完成" }; //调用WMS上传任务接口 HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestTask(requestMode).Result; if (modResponseTask.StatusCode == 0) { modTaskMonitor.InteractiveMsg = "手动上传给WMS任务完成"; modTask.IsSuccess = TaskSuccessEnum.Success; await _db.Updateable(modTask).ExecuteCommandAsync(); } else { Log.Error(string.Format("手动上传WMS任务反馈失败:StatusCode:{0};Msg:{1}", modResponseTask.StatusCode, modResponseTask.Msg)); } // 插入交互日志 await _db.Insertable(modTaskMonitor).ExecuteCommandAsync(); //下发任务日志 HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt()); } /// /// 任务置顶 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "TopUpTask")] [DisplayName("任务置顶")] public async Task TopUpTask(UpdateWcsTaskInput input) { var modTask = await _wcsTaskRep.GetByIdAsync(input.Id); if (modTask.Status != TaskStatusEnum.Wait) { throw Oops.Oh("只有等待执行的任务才能置顶!"); } int editNum = 1; List _editTaskNoList = new List(); //储位深度 string locatDepth = ""; if (modTask.TaskType == TaskTypeEnum.Out || modTask.TaskType == TaskTypeEnum.Move)//出库任务或入库任务 { locatDepth = modTask.StartLocate.Substring(modTask.StartLocate.Length - 1, 1);//起始储位深度 if (locatDepth == "2")//判断当前储位是否深度为2,内侧储位 { string locatString = modTask.StartLocate.Substring(0, modTask.StartLocate.Length - 1) + "1";//获取外侧储位地址 //判断外侧储位是否有等待执行的任务,有就优先执行 var modTask2 = _db.Queryable().First(w => w.IsDelete == false && w.Status == TaskStatusEnum.Wait && w.StartLocate == locatString); if (modTask2 != null) { modTask2.Levels = 1; await _wcsTaskRep.Context.Updateable(modTask2).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); _editTaskNoList.Add(modTask2.TaskNo); modTask.Levels = 2; await _wcsTaskRep.Context.Updateable(modTask).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); _editTaskNoList.Add(modTask.TaskNo); editNum = 2; } else { modTask.Levels = 1; await _wcsTaskRep.Context.Updateable(modTask).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); _editTaskNoList.Add(modTask.TaskNo); } } else { modTask.Levels = 1; await _wcsTaskRep.Context.Updateable(modTask).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); _editTaskNoList.Add(modTask.TaskNo); } } if (modTask.TaskType == TaskTypeEnum.In)//入库任务 { if (string.IsNullOrEmpty(modTask.EndLocate)) { throw Oops.Oh("该入库任务还未分配储位,置顶失败!"); } locatDepth = modTask.EndLocate.Substring(modTask.EndLocate.Length - 1, 1);//目标储位深度 if (locatDepth == "1")//判断当前储位是否深度为1,外侧储位 { string locatString = modTask.EndLocate.Substring(0, modTask.EndLocate.Length - 1) + "2";//获取内侧储位地址 //判断内侧储位是否有等待执行的任务,有就优先执行 var modTask2 = _db.Queryable().First(w => w.IsDelete == false && w.Status == TaskStatusEnum.Wait && (w.StartLocate == locatString || w.EndLocate == locatString)); if (modTask2 != null) { modTask2.Levels = 1; await _wcsTaskRep.Context.Updateable(modTask2).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); _editTaskNoList.Add(modTask2.TaskNo); modTask.Levels = 2; await _wcsTaskRep.Context.Updateable(modTask).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); _editTaskNoList.Add(modTask.TaskNo); editNum = 2; } else { modTask.Levels = 1; await _wcsTaskRep.Context.Updateable(modTask).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); _editTaskNoList.Add(modTask.TaskNo); } } else { modTask.Levels = 1; await _wcsTaskRep.Context.Updateable(modTask).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); _editTaskNoList.Add(modTask.TaskNo); } } //顺延其他置顶任务 var modTaskList = _db.Queryable().Where(w => w.IsDelete == false && w.Status == TaskStatusEnum.Wait && w.Levels != 999 && !_editTaskNoList.Contains(w.TaskNo)).ToList(); foreach (var item in modTaskList) { item.Levels += editNum; } await _wcsTaskRep.Context.Updateable(modTaskList).UpdateColumns(s => new { s.Levels }).ExecuteCommandAsync(); } /// /// 自动生成任务号 /// /// /// [NonAction] public string GetTaskCode(string codeFlag = "WCS") { var list = _db.Queryable().Where(m => m.TaskNo.StartsWith("WCS")).ToList(); string maxNo = list.Max(m => m.TaskNo); if (!string.IsNullOrEmpty(maxNo)) { maxNo = maxNo.Substring(codeFlag.Length); } //获取数据库时间八位 string date = DateTime.Now.ToString("yyyyMMdd").Trim(); string no = ""; if (string.IsNullOrEmpty(maxNo)) { no = codeFlag + date + "0001"; } else { if (maxNo.Length == 12 && maxNo.Substring(0, 8) == date) { int lastNo = Convert.ToInt32(maxNo.Substring(8, 4)) + 1; no = codeFlag + date + (lastNo.ToString().PadLeft(4, '0')); } else { no = codeFlag + date + "0001"; } } return no; } }