LocationRegionScopeHelper.cs
2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using FoodLabeling.Application.Services.DbModels;
using FoodLabeling.Domain.Entities;
using SqlSugar;
using Volo.Abp.Users;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace FoodLabeling.Application.Helpers;
/// <summary>
/// 门店列表数据范围:管理员可见全部;非管理员仅可见其 <c>userlocation</c> 绑定门店所属 Region
///(<c>location.Partner</c> + <c>location.GroupName</c>,与 <c>fl_group</c> 一致)。
/// </summary>
public static class LocationRegionScopeHelper
{
/// <summary>
/// 门店列表 Token 范围解析结果。
/// </summary>
public sealed class LocationListScopeFilter
{
public bool IsUnrestricted { get; init; }
public IReadOnlyList<(string Partner, string GroupName)> RegionKeys { get; init; } =
Array.Empty<(string, string)>();
}
/// <summary>
/// 解析当前用户可查询的 Region(公司 + 组织名)集合。
/// </summary>
public static async Task<LocationListScopeFilter> ResolveLocationListScopeAsync(
ICurrentUser currentUser,
ISqlSugarDbContext dbContext)
{
if (ReportsRoleHelper.IsAdminRole(currentUser))
{
return new LocationListScopeFilter { IsUnrestricted = true };
}
if (currentUser.Id is null)
{
return new LocationListScopeFilter();
}
var userId = currentUser.Id.Value.ToString();
var rows = await dbContext.SqlSugarClient.Queryable<UserLocationDbEntity>()
.InnerJoin<LocationAggregateRoot>((ul, loc) =>
!loc.IsDeleted && ul.LocationId == loc.Id.ToString())
.Where(ul => !ul.IsDeleted && ul.UserId == userId)
.Select((ul, loc) => new { loc.Partner, loc.GroupName })
.ToListAsync();
var keys = rows
.Where(x => !string.IsNullOrWhiteSpace(x.GroupName) && !string.IsNullOrWhiteSpace(x.Partner))
.Select(x => (Partner: x.Partner!.Trim(), GroupName: x.GroupName!.Trim()))
.Distinct()
.ToList();
return new LocationListScopeFilter { RegionKeys = keys };
}
/// <summary>
/// 将 Region 范围应用到 <c>location</c> 查询(须在其它 Where 之前或之后均可,建议在 IsDeleted 之后)。
/// </summary>
public static ISugarQueryable<LocationAggregateRoot> ApplyLocationListScope(
ISugarQueryable<LocationAggregateRoot> query,
LocationListScopeFilter scope)
{
if (scope.IsUnrestricted)
{
return query;
}
if (scope.RegionKeys.Count == 0)
{
return query.Where(_ => false);
}
var exp = Expressionable.Create<LocationAggregateRoot>();
foreach (var key in scope.RegionKeys)
{
var partner = key.Partner;
var groupName = key.GroupName;
exp = exp.Or(x => x.Partner == partner && x.GroupName == groupName);
}
return query.Where(exp.ToExpression());
}
}