using FoodLabeling.Application.Services.DbModels; using SqlSugar; using Volo.Abp; using Volo.Abp.Users; using Yi.Framework.Rbac.Domain.Entities; using Yi.Framework.SqlSugarCore.Abstractions; namespace FoodLabeling.Application.Helpers; /// /// App 打印日志 / 门店报表:门店绑定校验;管理员或 Partner 角色可查看当前门店全部打印记录。 /// public static class UsAppPrintLogScopeHelper { /// /// 管理员()或角色码/名含 partner(忽略大小写,如 Partner Admin)。 /// public static async Task CanViewAllPrintsAtLocationAsync( ICurrentUser currentUser, ISqlSugarClient db) { if (ReportsRoleHelper.IsAdminRole(currentUser)) { return true; } if (currentUser.Id is null) { return false; } var roleRows = await db.Ado.SqlQueryAsync( @"SELECT r.RoleCode, r.RoleName FROM UserRole ur INNER JOIN Role r ON ur.RoleId = r.Id WHERE ur.UserId = @UserId AND r.IsDeleted = 0 AND r.State = 1", new { UserId = currentUser.Id.Value }); return roleRows.Any(r => ContainsPartnerKeyword(r.RoleCode) || ContainsPartnerKeyword(r.RoleName)); } /// /// 校验当前用户是否绑定指定门店。 /// public static async Task EnsureUserBoundToLocationAsync( ICurrentUser currentUser, ISqlSugarClient db, string locationId) { if (currentUser.Id is null) { throw new UserFriendlyException("用户未登录"); } var lid = locationId.Trim(); var userIdStr = currentUser.Id.Value.ToString(); var bound = await db.Queryable() .AnyAsync(x => !x.IsDeleted && x.UserId == userIdStr && x.LocationId == lid); if (!bound) { throw new UserFriendlyException("当前账号未绑定该门店,无法查看"); } } /// /// 构建 App 门店打印任务查询(必选门店;可选仅当前用户)。 /// public static ISugarQueryable BuildLocationPrintTaskQuery( ISqlSugarClient db, string locationId, bool restrictToCreator, string currentUserIdStr) { var lid = locationId.Trim(); return db.Queryable() .LeftJoin((t, l) => t.LabelId == l.Id) .LeftJoin((t, l, p) => t.ProductId == p.Id) .LeftJoin((t, l, p, lt) => t.LabelTypeId == lt.Id) .LeftJoin((t, l, p, lt, tpl) => t.TemplateId == tpl.Id) .Where((t, l, p, lt, tpl) => t.LocationId == lid) .WhereIF(restrictToCreator, (t, l, p, lt, tpl) => t.CreatedBy == currentUserIdStr); } public static async Task> LoadOperatorNameMapAsync( ISqlSugarClient db, IEnumerable userIdStrings) { var map = new Dictionary(StringComparer.OrdinalIgnoreCase); var guids = userIdStrings .Where(x => !string.IsNullOrWhiteSpace(x)) .Select(x => x!.Trim()) .Select(x => Guid.TryParse(x, out var g) ? g : (Guid?)null) .Where(x => x.HasValue) .Select(x => x!.Value) .Distinct() .ToList(); if (guids.Count == 0) { return map; } var users = await db.Queryable() .Where(u => !u.IsDeleted && guids.Contains(u.Id)) .Select(u => new { u.Id, u.Name, u.Nick, u.UserName }) .ToListAsync(); foreach (var u in users) { var display = !string.IsNullOrWhiteSpace(u.Name) ? u.Name!.Trim() : !string.IsNullOrWhiteSpace(u.Nick) ? u.Nick!.Trim() : u.UserName?.Trim() ?? string.Empty; map[u.Id.ToString()] = string.IsNullOrWhiteSpace(display) ? "无" : display; } return map; } public static string ResolveOperatorName(IReadOnlyDictionary map, string? createdBy) { if (string.IsNullOrWhiteSpace(createdBy)) { return "无"; } return map.TryGetValue(createdBy.Trim(), out var name) ? name : "无"; } private static bool ContainsPartnerKeyword(string? value) => !string.IsNullOrWhiteSpace(value) && value.Trim().Contains("partner", StringComparison.OrdinalIgnoreCase); /// /// Label Report 聚合用(含分类 Join + 关键字筛选)。 /// public static ISugarQueryable BuildLocationPrintTaskReportQuery( ISqlSugarClient db, string locationId, bool restrictToCreator, string currentUserIdStr, string? keyword) { var lid = locationId.Trim(); var kw = keyword?.Trim(); return db.Queryable() .LeftJoin((t, l) => t.LabelId == l.Id) .LeftJoin((t, l, p) => t.ProductId == p.Id) .LeftJoin((t, l, p, lc) => l.LabelCategoryId == lc.Id) .LeftJoin((t, l, p, lc, pc) => p.CategoryId == pc.Id) .LeftJoin((t, l, p, lc, pc, lt) => t.LabelTypeId == lt.Id) .LeftJoin((t, l, p, lc, pc, lt, tpl) => t.TemplateId == tpl.Id) .Where((t, l, p, lc, pc, lt, tpl) => t.LocationId == lid) .WhereIF(restrictToCreator, (t, l, p, lc, pc, lt, tpl) => t.CreatedBy == currentUserIdStr) .WhereIF(!string.IsNullOrWhiteSpace(kw), (t, l, p, lc, pc, lt, tpl) => (p.ProductName != null && p.ProductName.Contains(kw!)) || (lc.CategoryName != null && lc.CategoryName.Contains(kw!)) || (pc.CategoryName != null && pc.CategoryName.Contains(kw!))); } private sealed class UserRoleRow { public string? RoleCode { get; set; } public string? RoleName { get; set; } } }