Files
jinko.yikatong/Src/Dlhis.Basic/Device/Services/Implements/BasePermissionAnalyzeService.cs

294 lines
12 KiB
C#

using Dlhis.Basic.Device.Dtos;
using Dlhis.Basic.Device.Request;
using Dlhis.Basic.Device.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 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;
/// <summary>
/// 权限分析基类
/// </summary>
public abstract class BasePermissionAnalyzeService : IPermissionAnalyzeService
{
private readonly IDevicePermissionAnalyzeService _devicePermissionAnalyzeService;
protected IDbContext DbContext { get; }
protected BasePermissionAnalyzeService(IServiceProvider serviceProvider)
{
ICurrentUser currentUser = serviceProvider.GetService<ICurrentUser>();
DbContext = serviceProvider.GetService<IDbContext>();
CurrentTenantId = currentUser.GetStringTenantId();
_devicePermissionAnalyzeService = serviceProvider.GetService<IDevicePermissionAnalyzeService>();
}
private string CurrentTenantId { get; }
public async Task<DevicePermissionAssignResponse> AnalyzeAsync(DevicePermissionSaveRequest request)
{
var source = request.UniqueType + "-" + request.AssignType;
var tasksToAdd = new List<DeviceTaskEntity>();
var tasksToDelete = new List<DeviceTaskEntity>();
await CheckWhetherAssignToTopDeviceGroupAsync(request);
await CheckAssignedToTenantAsync(request);
await CheckAssignAppointmentAndBusinessTripGroupAsync(request);
var dps = await _devicePermissionAnalyzeService.GetDevicePermissionsAsync(request);
try
{
(List<Guid> codesToAdd, List<Guid> codesToDelete) = await GetDiffAsync(request.UniqueType, dps, request.Codes);
if (codesToAdd.IsEmpty() && codesToDelete.IsEmpty())
{
return new DevicePermissionAssignResponse(0, 0);
}
var devicesToAdd = await DbContext.Queryable<DeviceEntity>().Where(x => codesToAdd.Contains(x.Code)).Distinct().ToListAsync();
var devicesToDelete = await DbContext.Queryable<DeviceEntity>().Where(x => codesToDelete.Contains(x.Code)).Distinct().ToListAsync();
var gainfoNos = await GetGainfoNosAsync(request.GetActualAssignValue(), request.Type);
var userTenantDeviceCodes = devicesToDelete.IsPresent() && request.AssignType != AssignTypeEnumType.Tenant
? await _devicePermissionAnalyzeService.GetUserAssignDeviceCodesWithTypeInTenantAsync(gainfoNos, request.UniqueType, request.GetActualAssignValue(), request.AssignType)
: new Dictionary<string, List<TenantAssignTypeDeviceCode>>();
foreach (var gainfoNo in gainfoNos)
{
IEnumerable<DeviceEntity> 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,
Source = source,
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,
Source = source,
Priority = 0,
TenantId = x.TenantId,
}).ToList());
}
await ChunkInsertAsync(tasksToAdd);
await ChunkInsertAsync(tasksToDelete);
}
finally
{
await PersistDataAsync(dps, request);
}
return new DevicePermissionAssignResponse(tasksToAdd.Count, tasksToDelete.Count);
}
/// <summary>
/// 获取分配当前类型关联的用户
/// </summary>
/// <param name="assignValue"></param>
/// <param name="deviceType"></param>
/// <returns></returns>
protected abstract Task<List<string>> GetGainfoNosAsync(string assignValue, DeviceTypeEnumType deviceType);
//************************************************************************************************************************
private async Task CheckAssignedToTenantAsync(DevicePermissionSaveRequest request)
{
if (request.AssignType != AssignTypeEnumType.Tenant)
{
(request.Type == DeviceTypeEnumType.Meal).ThrowIfTrue("餐饮设备需分配到厂区级别");
if (request.UniqueType == DeviceAssignmentTypeEnumType.Device)
{
if (await DbContext.Queryable<DevicePermissionEntity>()
.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<Guid>();
var deviceGroups = await DbContext.Queryable<DeviceGroupEntity>().ToListAsync();
request.Codes.ForEach(groupCode => result.AddRange(RecursionHelper.HandlerDeviceGroupNextCodes(groupCode, deviceGroups)));
if (await DbContext.Queryable<DevicePermissionEntity>()
.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<DeviceGroupRelationshipEntity>()
.Where(x => result.Contains(x.GroupCode))
.Select(x => x.DeviceCode).Distinct()
.ToListAsync();
if (await DbContext.Queryable<DevicePermissionEntity>()
.Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Device)
.Where(x => x.AssignType == AssignTypeEnumType.Tenant)
.Where(x => deviceCodes.Contains(x.UniqueValue))
.AnyAsync())
{
true.ThrowIfTrue("设备组存在关联设备已分配到厂区中");
}
}
}
}
private async Task ChunkInsertAsync<T>(List<T> batch) where T : class, new()
{
foreach (var tasks in batch.Chunk(500))
{
await DbContext.InsertAsync(tasks);
}
}
/// <summary>
/// 检查是否分配顶级的设备分组
/// </summary>
/// <param name="request"></param>
private static async Task CheckWhetherAssignToTopDeviceGroupAsync(DevicePermissionSaveRequest request)
{
if (request.UniqueType == DeviceAssignmentTypeEnumType.Group)
{
await Scoped.Temp.Value.CreateAsync(async sp =>
{
var currentDb = sp.GetService<IDbContext>();
await currentDb.IgnoreAsync<ITenantId>(async () =>
{
var dgs = await currentDb.Queryable<DeviceGroupEntity>().Where(x => request.Codes.Contains(x.Code)).ToListAsync();
dgs.Any(x => x.TenantId.IsEmpty()).ThrowIfTrue("不可分配顶级分组节点");
});
});
}
}
private async Task CheckAssignAppointmentAndBusinessTripGroupAsync(DevicePermissionSaveRequest request)
{
if (request.UniqueType == DeviceAssignmentTypeEnumType.Group && request.AssignType != AssignTypeEnumType.User)
{
if (await DbContext.Queryable<DeviceGroupEntity>().Where(x => request.Codes.Contains(x.Code))
.Where(x => x.AsAppointment || x.IsBusinessTrip)
.AnyAsync())
{
true.ThrowIfTrue("不可分配出差组和预约组");
}
}
}
/// <summary>
/// 持久化数据
/// </summary>
/// <param name="dps"></param>
/// <param name="request"></param>
private async Task PersistDataAsync(List<DevicePermissionEntity> 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);
}
}
/// <summary>
/// 获取现在权限与当前的分配之间的deviceCode差异
/// </summary>
/// <param name="type"></param>
/// <param name="dps"></param>
/// <param name="uniqueValues"></param>
/// <returns></returns>
private async Task<(List<Guid>, List<Guid>)> GetDiffAsync(DeviceAssignmentTypeEnumType type, List<DevicePermissionEntity> dps, List<Guid> uniqueValues)
{
var beforeCodes = dps.Select(x => x.UniqueValue).ToList();
var presentCodes = uniqueValues.IsPresent() ? uniqueValues : new List<Guid>();
if (type == DeviceAssignmentTypeEnumType.Group)
{
var deviceGroups = await DbContext.Queryable<DeviceGroupEntity>().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);
}
/// <summary>
/// 获取分组下的deviceCode
/// </summary>
/// <param name="codes"></param>
/// <param name="deviceGroups"></param>
/// <returns></returns>
private async Task<List<Guid>> GetDeviceCodeByGroupAsync(List<Guid> codes, List<DeviceGroupEntity> deviceGroups)
{
var result = new List<Guid>();
codes.ForEach(groupCode => result.AddRange(RecursionHelper.HandlerDeviceGroupNextCodes(groupCode, deviceGroups)));
result = result.Distinct().ToList();
return await DbContext.Queryable<DeviceGroupRelationshipEntity>()
.Where(x => result.Contains(x.GroupCode))
.Select(x => x.DeviceCode)
.Distinct()
.ToListAsync();
}
}