using FoodLabeling.Application.Services.DbModels;
using FoodLabeling.Domain.Entities;
using SqlSugar;
using Volo.Abp.Users;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace FoodLabeling.Application.Helpers;
///
/// 门店列表数据范围:管理员可见全部;非管理员仅可见其 userlocation 绑定门店所属 Region
///(location.Partner + location.GroupName,与 fl_group 一致)。
///
public static class LocationRegionScopeHelper
{
///
/// 门店列表 Token 范围解析结果。
///
public sealed class LocationListScopeFilter
{
public bool IsUnrestricted { get; init; }
public IReadOnlyList<(string Partner, string GroupName)> RegionKeys { get; init; } =
Array.Empty<(string, string)>();
}
///
/// 解析当前用户可查询的 Region(公司 + 组织名)集合。
/// Company Admin 展开为绑定 Company 下全部 Region(与 一致)。
///
public static async Task 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()
.InnerJoin((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 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()
.Where(p => !p.IsDeleted && partnerIds.Contains(p.Id))
.Select(p => new { p.Id, p.PartnerName })
.ToListAsync();
var groups = await db.Queryable()
.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() };
}
///
/// 将 Region 范围应用到 location 查询(须在其它 Where 之前或之后均可,建议在 IsDeleted 之后)。
///
public static ISugarQueryable ApplyLocationListScope(
ISugarQueryable query,
LocationListScopeFilter scope)
{
if (scope.IsUnrestricted)
{
return query;
}
if (scope.RegionKeys.Count == 0)
{
return query.Where(_ => false);
}
var exp = Expressionable.Create();
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());
}
}