PartnerScopeHelper.cs
6.88 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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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> 绑定门店所属公司。
/// </summary>
public static class PartnerScopeHelper
{
/// <summary>
/// <see cref="IsUnrestricted"/> 为 true 时不限制;
/// 否则仅 <see cref="AllowedPartnerIds"/> 中的公司 Id(<c>fl_partner.Id</c>)可见;无绑定时为空列表。
/// </summary>
public sealed class PartnerScopeFilter
{
public bool IsUnrestricted { get; init; }
public IReadOnlyList<string> AllowedPartnerIds { get; init; } = Array.Empty<string>();
}
/// <summary>
/// 解析当前登录用户可查询的合作伙伴 Id 范围。
/// </summary>
public static async Task<PartnerScopeFilter> ResolvePartnerScopeAsync(
ICurrentUser currentUser,
ISqlSugarDbContext dbContext)
{
if (ReportsRoleHelper.IsAdminRole(currentUser))
{
return new PartnerScopeFilter { IsUnrestricted = true };
}
if (currentUser.Id is null)
{
return new PartnerScopeFilter();
}
var userId = currentUser.Id.Value.ToString();
var locationIds = await dbContext.SqlSugarClient.Queryable<UserLocationDbEntity>()
.Where(x => !x.IsDeleted && x.UserId == userId)
.Select(x => x.LocationId)
.Distinct()
.ToListAsync();
if (locationIds.Count == 0)
{
return new PartnerScopeFilter();
}
var partnerKeys = await dbContext.SqlSugarClient.Queryable<LocationAggregateRoot>()
.Where(x => !x.IsDeleted && locationIds.Contains(x.Id.ToString()))
.Where(x => x.Partner != null && x.Partner != string.Empty)
.Select(x => x.Partner!)
.Distinct()
.ToListAsync();
if (partnerKeys.Count == 0)
{
return new PartnerScopeFilter();
}
var allowedIds = await dbContext.SqlSugarClient.Queryable<FlPartnerDbEntity>()
.Where(x => !x.IsDeleted)
.Where(x => partnerKeys.Contains(x.PartnerName) || partnerKeys.Contains(x.Id))
.Select(x => x.Id)
.Distinct()
.ToListAsync();
return new PartnerScopeFilter { AllowedPartnerIds = allowedIds };
}
/// <summary>
/// 将数据范围应用到合作伙伴查询(须在其它 Where 之前或之后均可,建议在 IsDeleted 之后)。
/// </summary>
public static ISugarQueryable<FlPartnerDbEntity> ApplyPartnerScope(
ISugarQueryable<FlPartnerDbEntity> query,
PartnerScopeFilter scope)
{
if (scope.IsUnrestricted)
{
return query;
}
var ids = scope.AllowedPartnerIds;
if (ids.Count == 0)
{
return query.Where(_ => false);
}
return query.Where(x => ids.Contains(x.Id));
}
/// <summary>
/// 组织(fl_group)数据范围:管理员可见全部;非管理员仅可见其 <c>userlocation</c> 绑定门店对应的 Region(公司 + 组织名与 location 一致)。
/// </summary>
public sealed class GroupScopeFilter
{
public bool IsUnrestricted { get; init; }
public IReadOnlyList<string> AllowedGroupIds { get; init; } = Array.Empty<string>();
}
/// <summary>
/// 解析当前登录用户可查询的组织 Id 范围(与 Reports 按 location.Partner + location.GroupName 对齐)。
/// </summary>
public static async Task<GroupScopeFilter> ResolveGroupScopeAsync(
ICurrentUser currentUser,
ISqlSugarDbContext dbContext)
{
if (ReportsRoleHelper.IsAdminRole(currentUser))
{
return new GroupScopeFilter { IsUnrestricted = true };
}
if (currentUser.Id is null)
{
return new GroupScopeFilter();
}
var userId = currentUser.Id.Value.ToString();
var locationRows = 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();
if (locationRows.Count == 0)
{
return new GroupScopeFilter();
}
var pairs = locationRows
.Where(x => !string.IsNullOrWhiteSpace(x.GroupName))
.Select(x => (Partner: (x.Partner ?? string.Empty).Trim(), GroupName: x.GroupName!.Trim()))
.Where(x => !string.IsNullOrEmpty(x.GroupName) && !string.IsNullOrEmpty(x.Partner))
.Distinct()
.ToList();
if (pairs.Count == 0)
{
return new GroupScopeFilter();
}
var partnerKeys = pairs.Select(x => x.Partner).Distinct().ToList();
var partners = await dbContext.SqlSugarClient.Queryable<FlPartnerDbEntity>()
.Where(x => !x.IsDeleted)
.Where(x => partnerKeys.Contains(x.PartnerName) || partnerKeys.Contains(x.Id))
.Select(x => new { x.Id, x.PartnerName })
.ToListAsync();
var allowedGroupIds = new HashSet<string>(StringComparer.Ordinal);
foreach (var pair in pairs)
{
var partnerId = partners
.FirstOrDefault(p =>
string.Equals(p.PartnerName, pair.Partner, StringComparison.Ordinal) ||
string.Equals(p.Id, pair.Partner, StringComparison.Ordinal))
?.Id;
if (string.IsNullOrEmpty(partnerId))
{
continue;
}
var ids = await dbContext.SqlSugarClient.Queryable<FlGroupDbEntity>()
.Where(g => !g.IsDeleted && g.PartnerId == partnerId && g.GroupName == pair.GroupName)
.Select(g => g.Id)
.ToListAsync();
foreach (var id in ids)
{
allowedGroupIds.Add(id);
}
}
return new GroupScopeFilter { AllowedGroupIds = allowedGroupIds.ToList() };
}
/// <summary>
/// 将组织数据范围应用到 fl_group 联表查询。
/// </summary>
public static ISugarQueryable<FlGroupDbEntity, FlPartnerDbEntity> ApplyGroupScope(
ISugarQueryable<FlGroupDbEntity, FlPartnerDbEntity> query,
GroupScopeFilter scope)
{
if (scope.IsUnrestricted)
{
return query;
}
var ids = scope.AllowedGroupIds;
if (ids.Count == 0)
{
return query.Where((g, p) => false);
}
return query.Where((g, p) => ids.Contains(g.Id));
}
}