using Dlhis.Basic.Device.Dtos; using Dlhis.Basic.Device.Response; using Dlhis.Basic.Device.Services; using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Response; using Dlhis.Basic.Utils; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; using Dlhis.Entity.Sys.Entities; using Dlhis.Entity.Sys.Enums; using Dlhis.Entity.Visitor.Entity; using Kurisu.AspNetCore; using Kurisu.AspNetCore.Authentication.Abstractions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils.Extensions; using Mapster; using SqlSugar; namespace Dlhis.Basic.Organization.Services.Implements; public class GainfoGroupService : IGainfoGroupService { private readonly IDbContext _dbContext; private readonly ICurrentUser _currentUser; private readonly IDevicePermissionAnalyzeService _devicePermissionAnalyzeService; public GainfoGroupService(IDbContext dbContext, ICurrentUser currentUser, IDevicePermissionAnalyzeService devicePermissionAnalyzeService) { _dbContext = dbContext; _currentUser = currentUser; _devicePermissionAnalyzeService = devicePermissionAnalyzeService; } public async Task> GetTreeAsync(string search) { var gainfoGroups = await _dbContext.Queryable() .Select() .ToListAsync(); var tops = gainfoGroups.Where(x => !x.PCode.HasValue).ToList(); tops.ForEach(x => { RecursionGetNext(x, gainfoGroups); }); return tops; } public async Task SaveAsync(GainfoGroupSaveRequest request) { await CheckDuplicateNameAsync(request); if (!request.Id.HasValue) { if (request.PCode.HasValue) { (await _dbContext.Queryable().Where(x => x.GroupCode == request.PCode).AnyAsync()).ThrowIfTrue("上级已分配人员"); } var entity = request.Adapt(); entity.Code = Guid.NewGuid(); await _dbContext.InsertAsync(entity); await _dbContext.InsertAsync(new DataPermissionEntity { AssignValue = _currentUser.GetStringSubjectId(), UniqueType = DataPermissionAssignmentEnumType.UserGroup, UniqueValue = entity.Code, DeviceType = null, TenantId = _currentUser.GetStringTenantId() }); } else { var entity = await _dbContext.Queryable().Where(x => x.Id == request.Id).SingleAsync(); request.Adapt(entity); await _dbContext.UpdateAsync(entity); } } public async Task> GetGainfosByGroupAsync(Guid code) { var userNos = await _dbContext.Queryable() .Where(x => x.GroupCode == code) .Select(x => x.UserNo) .ToListAsync(); var list = await _dbContext.Queryable() .Where(x => userNos.Contains(x.No)) .Select() .ToListAsync(); return list; } public async Task AssignGainfosAsync(GainfoAssignRequest request) { if (request.UserNos.IsPresent()) { var pGrp = await _dbContext.Queryable().Where(x => x.Code == request.GroupCode).FirstAsync(); (pGrp is { Editable: false, IsDefault: true }).ThrowIfTrue("不可分配人员到当前分组"); } var existsNextGroup = await _dbContext.Queryable().Where(x => x.PCode == request.GroupCode).AnyAsync(); existsNextGroup.ThrowIfTrue("存在下级分组,无法分配人员"); var relations = await _dbContext.Queryable() .Where(x => x.GroupCode == request.GroupCode) .ToListAsync(); var presentUserNos = await _dbContext.Queryable() .Where(x => request.UserNos.Contains(x.No) || request.UserNos.Contains(x.Code) ) //NO和工号匹配 .Select(x => x.No) .ToListAsync(); var queryableSetting = App.GetServiceProvider().GetService(); try { queryableSetting.EnableCrossTenant = false; var factories = _currentUser.GetUserClaim("tenants").Split(",").ToList(); var businessUserNos = await _dbContext.Queryable() .Where(x => request.UserNos.Contains(x.No) || request.UserNos.Contains(x.Code) ) .Where(x => SqlFunc.Subqueryable() .Where(p => p.Code == x.Code && factories.Contains(p.Destination) && SqlFunc.DateIsSame(p.BeginDate, DateTime.Now)) .Any()) .Select(x => x.No) .ToListAsync(); presentUserNos.AddRange(businessUserNos); } finally { queryableSetting.EnableCrossTenant = true; } //(userNos.Count != request.UserNos.Count).ThrowIfTrue("存在权限外人员,无法添加"); var r = await PermissionResetAsync(request.GroupCode, relations.Select(x => x.UserNo).Distinct().ToList(), presentUserNos); await _dbContext.DeleteAsync(relations); var entities = presentUserNos.Select(x => new GainfoGroupRelationshipEntity { GroupCode = request.GroupCode, UserNo = x }).ToList(); await _dbContext.InsertAsync(entities); return r; } private async Task PermissionResetAsync(Guid groupCode, List beforeUserNos, List presentUserNos) { var usersToAdd = presentUserNos.Except(beforeUserNos).ToList(); var usersToDelete = beforeUserNos.Except(presentUserNos).ToList(); if (usersToAdd.IsEmpty() && usersToDelete.IsEmpty()) { return new DevicePermissionAssignResponse(0, 0); } var gainfoGroups = await _dbContext.Queryable().ToListAsync(); var gainfoGroupCodes = RecursionHelper.HandlerGainfoGroupPreviousCodes(groupCode, gainfoGroups).Select(x => x.ToString()); var dps = await _dbContext.Queryable() .Where(x => x.AssignType == AssignTypeEnumType.Group) .Where(x => gainfoGroupCodes.Contains(x.AssignValue)) .ToListAsync(); //var result = new List(); var deviceGroups = dps.Any(x => x.UniqueType == DeviceAssignmentTypeEnumType.Group) ? await _dbContext.Queryable().ToListAsync() : new List(0); //只会循环2次 var deviceCodes = new List(); foreach (var devicePermissionGroup in dps.GroupBy(x => x.UniqueType)) { var codes = devicePermissionGroup.Select(x => x.UniqueValue).Distinct().ToList(); if (devicePermissionGroup.Key == DeviceAssignmentTypeEnumType.Group) { deviceCodes.AddRange(await GetDeviceCodeByGroupAsync(codes, deviceGroups)); } deviceCodes.AddRange(codes); } deviceCodes = deviceCodes.Distinct().ToList(); var devices = await _dbContext.Queryable().Where(x => deviceCodes.Contains(x.Code)).ToListAsync(); var userTenantDeviceCodes = usersToDelete.IsPresent() && dps.Exists(x => x.AssignType != AssignTypeEnumType.Tenant) ? await _devicePermissionAnalyzeService.GetUserAssignDeviceCodesWithTypeInTenantAsync(beforeUserNos.Union(presentUserNos).ToList()) : new Dictionary>(); var addTasks = new List(); var deleteTasks = new List(); foreach (var device in devices) { foreach (var item in usersToDelete) { if (userTenantDeviceCodes.TryGetValue(item, out var permissions)) { foreach (var permission in permissions) { permission.AssignTypes = permission.AssignTypes.Where(p => !gainfoGroupCodes.Contains(p.AssignValue)).ToList(); } var myDeviceCodes = permissions.SelectMany(x => x.AssignTypes).SelectMany(x => x.Codes); if (myDeviceCodes.Any(x => x == device.Code)) { continue; } deleteTasks.Add(new DeviceTaskEntity { Type = DeviceTaskEnumType.Delete, DeviceType = device.Type, UserId = null, UserNo = item, DeviceUniqueNo = device.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, Source = "手动操作人员分组关系", Priority = 0, TenantId = device.TenantId }); } } foreach (var item in usersToAdd) { addTasks.Add(new DeviceTaskEntity { Type = DeviceTaskEnumType.Add, DeviceType = device.Type, UserId = null, UserNo = item, DeviceUniqueNo = device.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, Source = "手动操作人员分组关系", Priority = 0, TenantId = device.TenantId }); } } await _dbContext.InsertAsync(addTasks); await _dbContext.InsertAsync(deleteTasks); return new DevicePermissionAssignResponse(addTasks.Count, deleteTasks.Count); } /// /// 获取分组下的deviceCode /// /// /// /// private async Task> GetDeviceCodeByGroupAsync(List codes, List deviceGroups) { var result = new List(); codes.ForEach(groupCode => result.AddRange(RecursionHelper.HandlerDeviceGroupNextCodes(groupCode, deviceGroups))); result = result.Distinct().ToList(); return await _dbContext.Queryable() .Where(x => result.Contains(x.GroupCode)) .Select(x => x.DeviceCode) .Distinct() .ToListAsync(); } public async Task> GetGainfoGroupsByUserCodeAsync(string userCode) { var gainfo = await _dbContext.Queryable().Where(x => x.Code == userCode).SingleAsync(); var userNo = gainfo?.No; return await _dbContext.Queryable() .LeftJoin((x, xg) => x.GroupCode == xg.Code) .Where((x, xg) => x.UserNo == userNo) .Select((x, xg) => new GainfoGroupTreeResponse { Id = x.Id, PCode = xg.PCode, Code = xg.Code, Name = xg.Name, Remark = xg.Remark, Editable = xg.Editable, IsDefault = xg.IsDefault, TenantId = xg.TenantId }) .ToListAsync(); } //******************************************************* help methods *********************************************************** /// /// 检查重名 /// /// /// private async Task CheckDuplicateNameAsync(GainfoGroupSaveRequest request) { var exists = await _dbContext.Queryable() .Where(x => x.Name == request.Name) .WhereIF(request.Id.HasValue, x => x.Id != request.Id) .AnyAsync(); exists.ThrowIfTrue($"重复组名{request.Name}"); } private void RecursionGetNext(GainfoGroupTreeResponse current, List gainfoGroups) { var currentTenantId = _currentUser.GetStringTenantId(); var next = gainfoGroups.Where(x => { if (x.PCode == current.Code) { if (x.TenantId.IsEmpty()) { return true; } else { return x.TenantId == currentTenantId; } } return false; }).ToList(); current.Next = next; foreach (var item in next) { RecursionGetNext(item, gainfoGroups); } } }