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()); } }