using FoodLabeling.Application.Services.DbModels;
using FoodLabeling.Domain.Entities;
using SqlSugar;
using Volo.Abp;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace FoodLabeling.Application.Helpers;
///
/// Region(fl_group.Id)与 Location(location.Id)范围解析:Region 落库对应 location.GroupName。
///
public static class LocationScopeBindingHelper
{
///
/// 列表筛选:门店 Id 优先,否则 Region(groupId),否则 Company(partnerId);均未传返回 null。
///
public static async Task?> ResolveFilteredLocationIdsForListAsync(
ISqlSugarClient db,
string? partnerId,
string? groupId,
string? locationId)
{
var locId = locationId?.Trim();
if (!string.IsNullOrWhiteSpace(locId))
{
if (!Guid.TryParse(locId, out var locationGuid))
{
return new List();
}
var exists = await db.Queryable()
.AnyAsync(x => !x.IsDeleted && x.Id == locationGuid);
return exists ? new List { locId } : new List();
}
var gid = groupId?.Trim();
var pid = partnerId?.Trim();
if (string.IsNullOrWhiteSpace(pid) && string.IsNullOrWhiteSpace(gid))
{
return null;
}
var q = db.Queryable().Where(x => !x.IsDeleted);
if (!string.IsNullOrWhiteSpace(gid))
{
var g = await db.Queryable()
.FirstAsync(x => !x.IsDeleted && x.Id == gid);
if (g is null)
{
return new List();
}
var gName = g.GroupName?.Trim() ?? string.Empty;
var partner = await db.Queryable()
.FirstAsync(x => !x.IsDeleted && x.Id == g.PartnerId);
var pName = partner?.PartnerName?.Trim() ?? string.Empty;
q = q.Where(x => x.GroupName == gName && x.Partner == pName);
}
else if (!string.IsNullOrWhiteSpace(pid))
{
var partner = await db.Queryable()
.FirstAsync(x => !x.IsDeleted && x.Id == pid);
if (partner is null)
{
return new List();
}
var pName = partner.PartnerName?.Trim() ?? string.Empty;
q = q.Where(x => x.Partner == pName);
}
return await q.Select(x => SqlFunc.ToString(x.Id)).ToListAsync();
}
///
/// 列表筛选:按门店 Id 优先,否则按 Region(groupId)解析门店主键;均未传返回 null。
///
public static async Task?> ResolveScopedLocationIdsAsync(
ISqlSugarClient db,
string? groupId,
string? locationId)
{
var locId = locationId?.Trim();
if (!string.IsNullOrWhiteSpace(locId))
{
if (!Guid.TryParse(locId, out var locationGuid))
{
return new List();
}
var exists = await db.Queryable()
.AnyAsync(x => !x.IsDeleted && x.Id == locationGuid);
return exists ? new List { locId } : new List();
}
var gid = groupId?.Trim();
if (string.IsNullOrWhiteSpace(gid))
{
return null;
}
return await ResolveLocationIdsFromGroupIdsAsync(db, new List { gid });
}
///
/// 将 Company(partnerId)、Region(groupIds)与显式 locationIds 合并为去重后的门店 Id 列表。
///
public static Task> MergeToLocationIdsAsync(
ISqlSugarClient db,
string? partnerId,
IReadOnlyList? groupIds,
IReadOnlyList? locationIds) =>
MergeToLocationIdsAsync(db,
string.IsNullOrWhiteSpace(partnerId) ? null : new[] { partnerId.Trim() },
groupIds,
locationIds);
///
/// 将 Company(partnerIds)、Region(groupIds)与显式 locationIds 合并为去重后的门店 Id 列表。
///
public static async Task> MergeToLocationIdsAsync(
ISqlSugarClient db,
IReadOnlyList? partnerIds,
IReadOnlyList? groupIds,
IReadOnlyList? locationIds)
{
var merged = new HashSet(StringComparer.Ordinal);
var fromPartner = await ResolveLocationIdsFromPartnerIdsAsync(db, partnerIds);
foreach (var id in fromPartner)
{
merged.Add(id);
}
var fromGroups = await ResolveLocationIdsFromGroupIdsAsync(db, groupIds);
foreach (var id in fromGroups)
{
merged.Add(id);
}
foreach (var id in NormalizeIds(locationIds))
{
merged.Add(id);
}
return merged.ToList();
}
///
/// 根据已绑定门店反推适用的 Company Id(fl_partner.Id)。
///
public static async Task> ResolvePartnerIdsFromLocationIdsAsync(
ISqlSugarClient db,
IReadOnlyList locationIds)
{
var ids = NormalizeIds(locationIds);
if (ids.Count == 0)
{
return new List();
}
var guidList = ids.Where(x => Guid.TryParse(x, out _)).Select(Guid.Parse).ToList();
if (guidList.Count == 0)
{
return new List();
}
var locs = await db.Queryable()
.Where(x => !x.IsDeleted && guidList.Contains(x.Id))
.ToListAsync();
if (locs.Count == 0)
{
return new List();
}
var partnerNames = locs
.Select(x => x.Partner?.Trim())
.Where(x => !string.IsNullOrEmpty(x))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
if (partnerNames.Count == 0)
{
return new List();
}
var partners = await db.Queryable()
.Where(x => !x.IsDeleted)
.ToListAsync();
var partnerIdSet = new HashSet(StringComparer.Ordinal);
foreach (var name in partnerNames)
{
var match = partners.FirstOrDefault(p =>
string.Equals(p.PartnerName?.Trim(), name, StringComparison.OrdinalIgnoreCase) ||
string.Equals(p.Id, name, StringComparison.OrdinalIgnoreCase));
if (match is not null && !string.IsNullOrWhiteSpace(match.Id))
{
partnerIdSet.Add(match.Id.Trim());
}
}
return partnerIdSet.OrderBy(x => x, StringComparer.Ordinal).ToList();
}
///
/// 解析 Company(fl_partner.Id)下全部未删除门店 Id。
///
public static async Task> ResolveLocationIdsFromPartnerIdsAsync(
ISqlSugarClient db,
IReadOnlyList? partnerIds)
{
var ids = NormalizeIds(partnerIds);
if (ids.Count == 0)
{
return new List();
}
var result = new HashSet(StringComparer.Ordinal);
foreach (var pid in ids)
{
var partner = await db.Queryable()
.FirstAsync(x => !x.IsDeleted && x.Id == pid);
if (partner is null)
{
continue;
}
var pName = partner.PartnerName?.Trim() ?? string.Empty;
if (string.IsNullOrEmpty(pName))
{
continue;
}
var locIds = await db.Queryable()
.Where(x => !x.IsDeleted && x.Partner == pName)
.Select(x => SqlFunc.ToString(x.Id))
.ToListAsync();
foreach (var lid in locIds.Where(x => !string.IsNullOrWhiteSpace(x)))
{
result.Add(lid.Trim());
}
}
return result.ToList();
}
///
/// 根据已绑定门店反推适用的 Region Id(fl_group.Id)。
///
public static async Task> ResolveGroupIdsFromLocationIdsAsync(
ISqlSugarClient db,
IReadOnlyList locationIds)
{
var ids = NormalizeIds(locationIds);
if (ids.Count == 0)
{
return new List();
}
var guidList = ids.Where(x => Guid.TryParse(x, out _)).Select(Guid.Parse).ToList();
if (guidList.Count == 0)
{
return new List();
}
var locs = await db.Queryable()
.Where(x => !x.IsDeleted && guidList.Contains(x.Id))
.ToListAsync();
if (locs.Count == 0)
{
return new List();
}
var partners = await db.Queryable()
.Where(x => !x.IsDeleted)
.ToListAsync();
var partnerNameToId = partners
.Where(x => !string.IsNullOrWhiteSpace(x.PartnerName))
.GroupBy(x => x.PartnerName!.Trim(), StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.First().Id, StringComparer.OrdinalIgnoreCase);
var groups = await db.Queryable()
.Where(x => !x.IsDeleted)
.ToListAsync();
var groupIdSet = new HashSet(StringComparer.Ordinal);
foreach (var loc in locs)
{
var gName = loc.GroupName?.Trim();
var pName = loc.Partner?.Trim();
if (string.IsNullOrEmpty(gName) || string.IsNullOrEmpty(pName))
{
continue;
}
if (!partnerNameToId.TryGetValue(pName, out var partnerId))
{
continue;
}
var match = groups.FirstOrDefault(g =>
g.PartnerId == partnerId &&
string.Equals(g.GroupName?.Trim(), gName, StringComparison.OrdinalIgnoreCase));
if (match is not null && !string.IsNullOrWhiteSpace(match.Id))
{
groupIdSet.Add(match.Id.Trim());
}
}
return groupIdSet.OrderBy(x => x, StringComparer.Ordinal).ToList();
}
///
/// 解析 Region(fl_group.Id)下全部未删除门店 Id。
///
public static async Task> ResolveLocationIdsFromGroupIdsAsync(
ISqlSugarClient db,
IReadOnlyList? groupIds)
{
var ids = NormalizeIds(groupIds);
if (ids.Count == 0)
{
return new List();
}
var result = new HashSet(StringComparer.Ordinal);
foreach (var gid in ids)
{
var g = await db.Queryable()
.FirstAsync(x => !x.IsDeleted && x.Id == gid);
if (g is null)
{
continue;
}
var partner = await db.Queryable()
.FirstAsync(x => !x.IsDeleted && x.Id == g.PartnerId);
var pName = partner?.PartnerName?.Trim() ?? string.Empty;
var gName = g.GroupName?.Trim() ?? string.Empty;
if (string.IsNullOrEmpty(pName) || string.IsNullOrEmpty(gName))
{
continue;
}
var locIds = await db.Queryable()
.Where(x => !x.IsDeleted && x.Partner == pName && x.GroupName == gName)
.Select(x => SqlFunc.ToString(x.Id))
.ToListAsync();
foreach (var lid in locIds.Where(x => !string.IsNullOrWhiteSpace(x)))
{
result.Add(lid.Trim());
}
}
return result.ToList();
}
///
/// 校验合并后的门店 Id 均存在。
///
public static async Task ValidateLocationIdsExistAsync(ISqlSugarClient db, IReadOnlyList locationIds)
{
var ids = NormalizeIds(locationIds);
if (ids.Count == 0)
{
return;
}
foreach (var id in ids)
{
if (!Guid.TryParse(id, out _))
{
throw new UserFriendlyException("门店Id格式不正确");
}
}
var guidList = ids.Select(Guid.Parse).ToList();
var existCount = await db.Queryable()
.Where(x => !x.IsDeleted && guidList.Contains(x.Id))
.CountAsync();
if (existCount != ids.Count)
{
throw new UserFriendlyException("门店不存在");
}
}
public static List NormalizeIds(IReadOnlyList? raw)
{
return raw?
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => x.Trim())
.Distinct(StringComparer.Ordinal)
.ToList() ?? new List();
}
}