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 打印日志 / 门店报表:门店绑定校验;同一门店下已绑定账号可查看该门店全部打印记录(不按 CreatedBy 过滤)。
///
public static class UsAppPrintLogScopeHelper
{
///
/// 管理员、Company Admin,或角色码/名含 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;
}
if (await TeamMemberRoleHelper.IsCompanyAdminUserAsync(db, currentUser))
{
return true;
}
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));
}
///
/// 校验当前用户是否可访问指定门店(含 Company Admin 公司下全部门店)。
///
public static async Task EnsureUserBoundToLocationAsync(
ICurrentUser currentUser,
ISqlSugarClient db,
string locationId)
{
await EnsureUserCanAccessLocationAsync(currentUser, db, locationId);
}
///
/// 校验是否可访问指定门店:平台管理员不校验;Company Admin 可访问绑定 Company 下任意门店;其它账号须 userlocation 绑定。
///
public static async Task EnsureUserCanAccessLocationAsync(
ICurrentUser currentUser,
ISqlSugarClient db,
string locationId)
{
if (ReportsRoleHelper.IsAdminRole(currentUser))
{
return;
}
if (currentUser.Id is null)
{
throw new UserFriendlyException("用户未登录");
}
var lid = TeamMemberListScopeHelper.NormalizeScopeKey(locationId);
if (string.IsNullOrEmpty(lid))
{
throw new UserFriendlyException("门店参数无效");
}
var accessible = await LocationScopeBindingHelper.ResolveAppAccessibleLocationIdsForUserAsync(
db, currentUser.Id.Value, currentUser);
if (!accessible.Contains(lid, StringComparer.OrdinalIgnoreCase))
{
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 => TeamMemberListScopeHelper.NormalizeScopeKey(x!))
.Where(x => Guid.TryParse(x, out _))
.Select(Guid.Parse)
.Distinct()
.ToList();
if (guids.Count == 0)
{
return map;
}
var parameters = new List(guids.Count);
var inClause = new List(guids.Count);
for (var i = 0; i < guids.Count; i++)
{
var paramName = $"@uid{i}";
inClause.Add(paramName);
parameters.Add(new SugarParameter(paramName, guids[i]));
}
var users = await db.Ado.SqlQueryAsync(
$"""
SELECT Id, UserName, Name, Nick
FROM User
WHERE IsDeleted = 0 AND Id IN ({string.Join(", ", inClause)})
""",
parameters);
foreach (var u in users)
{
var display = BuildOperatorDisplayName(u.Name, u.Nick, u.UserName);
map[TeamMemberListScopeHelper.UserKey(u.Id)] = display;
}
return map;
}
public static string ResolveOperatorName(IReadOnlyDictionary map, string? createdBy)
{
if (string.IsNullOrWhiteSpace(createdBy))
{
return "无";
}
var key = TeamMemberListScopeHelper.NormalizeScopeKey(createdBy);
return map.TryGetValue(key, out var name) ? name : "无";
}
private static string BuildOperatorDisplayName(string? name, string? nick, string? userName)
{
if (!string.IsNullOrWhiteSpace(name))
{
return name.Trim();
}
if (!string.IsNullOrWhiteSpace(nick))
{
return nick.Trim();
}
var user = userName?.Trim();
return string.IsNullOrWhiteSpace(user) ? "无" : user;
}
private sealed class OperatorUserRow
{
public Guid Id { get; set; }
public string? UserName { get; set; }
public string? Name { get; set; }
public string? Nick { get; set; }
}
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; }
}
}