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