LocationRegionScopeHelper.cs
5.16 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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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(公司 + 组织名)集合。
/// Company Admin 展开为绑定 Company 下全部 Region(与 <see cref="GroupListScopeHelper"/> 一致)。
/// </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 db = dbContext.SqlSugarClient;
if (await TeamMemberRoleHelper.IsCompanyAdminUserAsync(db, currentUser))
{
return await ResolveCompanyAdminLocationListScopeAsync(db, currentUser.Id.Value);
}
var userId = currentUser.Id.Value.ToString();
var rows = await db.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 };
}
private static async Task<LocationListScopeFilter> ResolveCompanyAdminLocationListScopeAsync(
ISqlSugarClient db,
Guid userId)
{
var locationIds = await LocationScopeBindingHelper.ResolveBoundLocationIdsForUserAsync(db, userId);
if (locationIds.Count == 0)
{
return new LocationListScopeFilter();
}
var partnerIds = await LocationScopeBindingHelper.ResolvePartnerIdsFromLocationIdsAsync(db, locationIds);
if (partnerIds.Count == 0)
{
return new LocationListScopeFilter();
}
var partners = await db.Queryable<FlPartnerDbEntity>()
.Where(p => !p.IsDeleted && partnerIds.Contains(p.Id))
.Select(p => new { p.Id, p.PartnerName })
.ToListAsync();
var groups = await db.Queryable<FlGroupDbEntity>()
.Where(g => !g.IsDeleted && partnerIds.Contains(g.PartnerId))
.Select(g => new { g.PartnerId, g.GroupName })
.ToListAsync();
var keys = new HashSet<(string Partner, string GroupName)>();
foreach (var group in groups)
{
var groupName = group.GroupName?.Trim();
if (string.IsNullOrEmpty(groupName))
{
continue;
}
var partner = partners.FirstOrDefault(p =>
string.Equals(p.Id, group.PartnerId, StringComparison.OrdinalIgnoreCase));
var partnerName = partner?.PartnerName?.Trim();
if (!string.IsNullOrEmpty(partnerName))
{
keys.Add((partnerName, groupName));
}
var partnerId = group.PartnerId?.Trim();
if (!string.IsNullOrEmpty(partnerId))
{
keys.Add((partnerId, groupName));
}
}
return new LocationListScopeFilter { RegionKeys = keys.ToList() };
}
/// <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());
}
}