using Admin.NET.Plugin.AiDOP.Dto.S8; using Admin.NET.Plugin.AiDOP.Entity.S0.Manufacturing; using Admin.NET.Plugin.AiDOP.Entity.S0.Warehouse; using Admin.NET.Plugin.AiDOP.Entity.S8; using Admin.NET.Plugin.AiDOP.Infrastructure; using Admin.NET.Plugin.AiDOP.Infrastructure.S8; namespace Admin.NET.Plugin.AiDOP.Service.S8; public class S8ExceptionService : ITransient { private readonly SqlSugarRepository _rep; private readonly SqlSugarRepository _deptRep; private readonly SqlSugarRepository _empRep; public S8ExceptionService( SqlSugarRepository rep, SqlSugarRepository deptRep, SqlSugarRepository empRep) { _rep = rep; _deptRep = deptRep; _empRep = empRep; } public async Task<(int total, List list)> GetPagedAsync(AdoS8ExceptionQueryDto q) { (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize); var pendingStatuses = new[] { "NEW", "ASSIGNED", "IN_PROGRESS", "PENDING_VERIFICATION" }; var query = _rep.Context.Queryable() .LeftJoin((e, sc) => e.TenantId == sc.TenantId && e.FactoryId == sc.FactoryId && e.SceneCode == sc.SceneCode) .Where((e, sc) => e.TenantId == q.TenantId && e.FactoryId == q.FactoryId && !e.IsDeleted) .WhereIF(!string.IsNullOrWhiteSpace(q.Status), (e, sc) => e.Status == q.Status) .WhereIF(string.IsNullOrWhiteSpace(q.Status) && q.StatusBucket == "pending", (e, sc) => pendingStatuses.Contains(e.Status)) .WhereIF(!string.IsNullOrWhiteSpace(q.Severity), (e, sc) => e.Severity == q.Severity) .WhereIF(!string.IsNullOrWhiteSpace(q.SceneCode), (e, sc) => e.SceneCode == q.SceneCode) .WhereIF(!string.IsNullOrWhiteSpace(q.ModuleCode), (e, sc) => e.ModuleCode == q.ModuleCode) .WhereIF(q.DeptId.HasValue, (e, sc) => e.ResponsibleDeptId == q.DeptId!.Value || e.OccurrenceDeptId == q.DeptId!.Value) .WhereIF(q.TimeoutFlag.HasValue, (e, sc) => e.TimeoutFlag == q.TimeoutFlag!.Value) .WhereIF(q.BeginTime.HasValue, (e, sc) => e.CreatedAt >= q.BeginTime!.Value) .WhereIF(q.EndTime.HasValue, (e, sc) => e.CreatedAt <= q.EndTime!.Value) .WhereIF(!string.IsNullOrWhiteSpace(q.ProcessNodeCode), (e, sc) => e.ProcessNodeCode == q.ProcessNodeCode) .WhereIF(!string.IsNullOrWhiteSpace(q.RelatedObjectCode), (e, sc) => e.RelatedObjectCode == q.RelatedObjectCode) .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), (e, sc) => e.Title.Contains(q.Keyword!) || e.ExceptionCode.Contains(q.Keyword!)); var total = await query.CountAsync(); var list = await query .OrderBy((e, sc) => e.CreatedAt, OrderByType.Desc) .Select((e, sc) => new AdoS8ExceptionListItemDto { Id = e.Id, FactoryId = e.FactoryId, ExceptionCode = e.ExceptionCode, Title = e.Title, Status = e.Status, Severity = e.Severity, PriorityScore = e.PriorityScore, PriorityLevel = e.PriorityLevel, SceneCode = e.SceneCode, SceneName = sc.SceneName, ResponsibleDeptId = e.ResponsibleDeptId, AssigneeId = e.AssigneeId, SlaDeadline = e.SlaDeadline, TimeoutFlag = e.TimeoutFlag, CreatedAt = e.CreatedAt, ClosedAt = e.ClosedAt }) .ToPageListAsync(q.Page, q.PageSize); foreach (var r in list) { r.StatusLabel = S8Labels.StatusLabel(r.Status); r.SeverityLabel = S8Labels.SeverityLabel(r.Severity); } await FillDisplayNamesAsync(list); return (total, list); } public async Task GetFilterOptionsAsync(long tenantId, long factoryId) { var scenes = await _rep.Context.Queryable() .Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && x.Enabled) .OrderBy(x => x.SortNo) .Select(x => new { value = x.SceneCode, label = x.SceneName }) .ToListAsync(); var departments = await _deptRep.AsQueryable() .Where(x => x.FactoryRefId == factoryId) .OrderBy(x => x.Department) .Take(500) .Select(x => new { value = x.Id, label = x.Descr ?? x.Department }) .ToListAsync(); return new { statuses = S8Labels.StatusOptions(), severities = S8Labels.SeverityOptions(), scenes, departments }; } public async Task GetDetailAsync(long id, long tenantId, long factoryId) { var rows = await _rep.Context.Queryable() .LeftJoin((e, sc) => e.TenantId == sc.TenantId && e.FactoryId == sc.FactoryId && e.SceneCode == sc.SceneCode) .Where((e, sc) => e.Id == id && e.TenantId == tenantId && e.FactoryId == factoryId && !e.IsDeleted) .Select((e, sc) => new AdoS8ExceptionDetailDto { Id = e.Id, FactoryId = e.FactoryId, ExceptionCode = e.ExceptionCode, Title = e.Title, Description = e.Description, Status = e.Status, Severity = e.Severity, PriorityScore = e.PriorityScore, PriorityLevel = e.PriorityLevel, SceneCode = e.SceneCode, SceneName = sc.SceneName, SourceType = e.SourceType, OccurrenceDeptId = e.OccurrenceDeptId, ResponsibleDeptId = e.ResponsibleDeptId, ResponsibleGroupId = e.ResponsibleGroupId, AssigneeId = e.AssigneeId, ReporterId = e.ReporterId, SlaDeadline = e.SlaDeadline, TimeoutFlag = e.TimeoutFlag, CreatedAt = e.CreatedAt, ClosedAt = e.ClosedAt, AssignedAt = e.AssignedAt, UpdatedAt = e.UpdatedAt, ActiveFlowInstanceId = e.ActiveFlowInstanceId, ActiveFlowBizType = e.ActiveFlowBizType, VerifierId = e.VerifierId, VerificationAssignedAt = e.VerificationAssignedAt, VerifiedAt = e.VerifiedAt, VerificationResult = e.VerificationResult, VerificationRemark = e.VerificationRemark, }) .Take(1) .ToListAsync(); if (rows.Count == 0) return null; var d = rows[0]; d.StatusLabel = S8Labels.StatusLabel(d.Status); d.SeverityLabel = S8Labels.SeverityLabel(d.Severity); await FillDisplayNamesAsync(new[] { d }); return d; } private async Task FillDisplayNamesAsync(IEnumerable rows) { var list = rows.ToList(); if (list.Count == 0) return; var deptIds = list .Select(x => x.ResponsibleDeptId) .Concat(list.OfType().Select(x => x.OccurrenceDeptId)) .Where(x => x > 0) .Distinct() .ToList(); var empIds = list .Select(x => x.AssigneeId ?? 0L) .Concat(list.OfType().Select(x => x.ReporterId ?? 0L)) .Concat(list.OfType().Select(x => x.VerifierId ?? 0L)) .Where(x => x > 0) .Distinct() .ToList(); var deptMap = deptIds.Count == 0 ? new Dictionary() : (await _deptRep.AsQueryable() .Where(x => deptIds.Contains(x.Id)) .Select(x => new { x.Id, Name = x.Descr ?? x.Department }) .ToListAsync()) .ToDictionary(x => x.Id, x => x.Name); var empMap = empIds.Count == 0 ? new Dictionary() : (await _empRep.AsQueryable() .Where(x => empIds.Contains(x.Id)) .Select(x => new { x.Id, Name = x.Name ?? x.Employee }) .ToListAsync()) .ToDictionary(x => x.Id, x => x.Name); foreach (var row in list) { if (row is AdoS8ExceptionDetailDto detail) { detail.ResponsibleDeptName = deptMap.GetValueOrDefault(detail.ResponsibleDeptId); detail.OccurrenceDeptName = deptMap.GetValueOrDefault(detail.OccurrenceDeptId); detail.AssigneeName = detail.AssigneeId.HasValue ? empMap.GetValueOrDefault(detail.AssigneeId.Value) : null; detail.ReporterName = detail.ReporterId.HasValue ? empMap.GetValueOrDefault(detail.ReporterId.Value) : null; detail.VerifierName = detail.VerifierId.HasValue ? empMap.GetValueOrDefault(detail.VerifierId.Value) : null; } else { row.ResponsibleDeptName = deptMap.GetValueOrDefault(row.ResponsibleDeptId); row.AssigneeName = row.AssigneeId.HasValue ? empMap.GetValueOrDefault(row.AssigneeId.Value) : null; } } } }