using Dlhis.Basic.Device.Dtos; using Dlhis.Basic.Device.Request; using Dlhis.Basic.Device.Response; 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 Kurisu.AspNetCore.Authentication.Abstractions; using Kurisu.AspNetCore.DataAccess.Entity; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Scope; using Kurisu.AspNetCore.Utils.Extensions; namespace Dlhis.Basic.Device.Services.Implements; /// /// 权限分析基类 /// public abstract class BasePermissionAnalyzeService : IPermissionAnalyzeService { private readonly IDevicePermissionAnalyzeService _devicePermissionAnalyzeService; protected IDbContext DbContext { get; } protected BasePermissionAnalyzeService(IServiceProvider serviceProvider) { ICurrentUser currentUser = serviceProvider.GetService(); DbContext = serviceProvider.GetService(); CurrentTenantId = currentUser.GetStringTenantId(); _devicePermissionAnalyzeService = serviceProvider.GetService(); } private string CurrentTenantId { get; } public async Task AnalyzeAsync(DevicePermissionSaveRequest request) { var tasksToAdd = new List(); var tasksToDelete = new List(); await CheckWhetherAssignToTopDeviceGroupAsync(request); await CheckAssignedToTenantAsync(request); var dps = await _devicePermissionAnalyzeService.GetDevicePermissions(request); try { (List codesToAdd, List codesToDelete) = await GetDiffAsync(request.UniqueType, dps, request.Codes); if (codesToAdd.IsEmpty() && codesToDelete.IsEmpty()) { return new DevicePermissionAssignResponse(0, 0); } var devicesToAdd = await DbContext.Queryable().Where(x => codesToAdd.Contains(x.Code)).Distinct().ToListAsync(); var devicesToDelete = await DbContext.Queryable().Where(x => codesToDelete.Contains(x.Code)).Distinct().ToListAsync(); var gainfoNos = await GetGainfoNosAsync(request.GetActualAssignValue()); var userTenantDeviceCodes = devicesToDelete.IsPresent() && request.AssignType != AssignTypeEnumType.Tenant ? await _devicePermissionAnalyzeService.GetUserAssignDeviceCodesWithTypeInTenantAsync(gainfoNos, request.UniqueType, request.GetActualAssignValue(), request.AssignType) : new Dictionary>(); foreach (var gainfoNo in gainfoNos) { IEnumerable currentDevicesToDelete = devicesToDelete; if (userTenantDeviceCodes.Any()) { var myDeviceCodes = userTenantDeviceCodes[gainfoNo].SelectMany(x => x.AssignTypes).SelectMany(x => x.Codes); var actToDeleteCodes = codesToDelete.Except(myDeviceCodes); currentDevicesToDelete = devicesToDelete.Where(p => actToDeleteCodes.Contains(p.Code)); } tasksToAdd.AddRange(devicesToAdd.Select(x => new DeviceTaskEntity { Type = DeviceTaskEnumType.Add, DeviceType = x.Type, UserId = null, UserNo = gainfoNo, DeviceUniqueNo = x.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = x.TenantId, }).ToList()); tasksToDelete.AddRange(currentDevicesToDelete.Select(x => new DeviceTaskEntity { Type = DeviceTaskEnumType.Delete, DeviceType = x.Type, UserId = null, UserNo = gainfoNo, DeviceUniqueNo = x.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = x.TenantId, }).ToList()); } await ChunkInsertAsync(tasksToAdd); await ChunkInsertAsync(tasksToDelete); } finally { await PersistDataAsync(dps, request); } return new DevicePermissionAssignResponse(tasksToAdd.Count, tasksToDelete.Count); } public async Task CheckAssignedToTenantAsync(DevicePermissionSaveRequest request) { if (request.AssignType != AssignTypeEnumType.Tenant) { (request.Type == DeviceTypeEnumType.Meal).ThrowIfTrue("餐饮设备需分配到厂区级别"); if (request.UniqueType == DeviceAssignmentTypeEnumType.Device) { if (await DbContext.Queryable() .Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Device) .Where(x => x.AssignType == AssignTypeEnumType.Tenant) .Where(x => request.Codes.Contains(x.UniqueValue)) .AnyAsync()) { true.ThrowIfTrue("存在设备分配到厂区中"); } } if (request.UniqueType == DeviceAssignmentTypeEnumType.Group) { var result = new List(); var deviceGroups = await DbContext.Queryable().ToListAsync(); request.Codes.ForEach(groupCode => result.AddRange(RecursionHelper.HandlerDeviceGroupNextCodes(groupCode, deviceGroups))); if (await DbContext.Queryable() .Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Group) .Where(x => x.AssignType == AssignTypeEnumType.Tenant) .Where(x => result.Contains(x.UniqueValue)) .AnyAsync()) { true.ThrowIfTrue("存在设备组分配到厂区中"); } var deviceCodes = await DbContext.Queryable() .Where(x => result.Contains(x.GroupCode)) .Select(x => x.DeviceCode).Distinct() .ToListAsync(); if (await DbContext.Queryable() .Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Device) .Where(x => x.AssignType == AssignTypeEnumType.Tenant) .Where(x => deviceCodes.Contains(x.UniqueValue)) .AnyAsync()) { true.ThrowIfTrue("设备组存在关联设备已分配到厂区中"); } } } } /// /// 获取分配当前类型关联的用户 /// /// /// protected abstract Task> GetGainfoNosAsync(string assignValue); // --------------------------------------------------------------------------------------------------------------------- // private async Task ChunkInsertAsync(List batch) where T : class, new() { foreach (var tasks in batch.Chunk(500)) { await DbContext.InsertAsync(tasks); } } /// /// 检查是否分配顶级的设备分组 /// /// private static async Task CheckWhetherAssignToTopDeviceGroupAsync(DevicePermissionSaveRequest request) { if (request.UniqueType == DeviceAssignmentTypeEnumType.Group) { await Scoped.Temp.Value.CreateAsync(async sp => { var currentDb = sp.GetService(); await currentDb.IgnoreAsync(async () => { var dgs = await currentDb.Queryable().Where(x => request.Codes.Contains(x.Code)).ToListAsync(); dgs.Any(x => x.TenantId.IsEmpty()).ThrowIfTrue("不可分配顶级分组节点"); }); }); } } /// /// 持久化数据 /// /// /// private async Task PersistDataAsync(List dps, DevicePermissionSaveRequest request) { await DbContext.DeleteAsync(dps); //保存配置的权限 if (request.Codes.IsPresent()) { var devicePermissions = request.Codes.Select(code => new DevicePermissionEntity { AssignType = request.AssignType, AssignValue = request.GetActualAssignValue(), UniqueType = request.UniqueType, UniqueValue = code, Type = request.Type, TenantId = CurrentTenantId }).ToList(); await DbContext.InsertAsync(devicePermissions); } } /// /// 获取现在权限与当前的分配之间的deviceCode差异 /// /// /// /// /// private async Task<(List, List)> GetDiffAsync(DeviceAssignmentTypeEnumType type, List dps, List uniqueValues) { var beforeCodes = dps.Select(x => x.UniqueValue).ToList(); var presentCodes = uniqueValues.IsPresent() ? uniqueValues : new List(); if (type == DeviceAssignmentTypeEnumType.Group) { var deviceGroups = await DbContext.Queryable().ToListAsync(); beforeCodes = await GetDeviceCodeByGroupAsync(beforeCodes, deviceGroups); presentCodes = await GetDeviceCodeByGroupAsync(presentCodes, deviceGroups); } var codesToAdd = presentCodes.Except(beforeCodes).ToList(); var codesToDelete = beforeCodes.Except(presentCodes).ToList(); return (codesToAdd, codesToDelete); } /// /// 获取分组下的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(); } }