using SqlSugar;
namespace Admin.NET.Plugin.AiDOP.Infrastructure;
///
/// Domain ↔ Ai-DOP tenant 解析器。
/// 直接查询 sys_tenant 系统租户表验证租户有效性,无需手动维护映射表。
/// Domain 优先取 GeneralizedCodeMaster.SystemConfig.CompanyCode,回落 8010。
///
public sealed class SourceDomainTenantResolver : ITransient
{
private readonly ISqlSugarClient _db;
public SourceDomainTenantResolver(ISqlSugarClient db) => _db = db;
///
/// 根据 sourceCode + domain 解析 tenant_id。
/// 直接查询 sys_tenant:返回第一个启用租户的 Id。
///
public async Task ResolveTenantIdAsync(
string sourceCode,
string domain,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(sourceCode) || string.IsNullOrWhiteSpace(domain))
throw new InvalidOperationException("sourceCode/domain 不能为空");
var rows = await _db.Ado.SqlQueryAsync(
"""
SELECT Id AS TenantId
FROM SysTenant
WHERE Status = 1
ORDER BY Id
LIMIT 1
""");
if (rows.Count == 0)
throw new InvalidOperationException("未找到启用的系统租户");
if (rows[0].TenantId <= 0)
throw new InvalidOperationException("系统租户 Id 非法");
return rows[0].TenantId;
}
///
/// 根据 sourceCode + tenantId 解析 domain。
/// 先在 sys_tenant 验证租户存在且启用,再从 GeneralizedCodeMaster 取公司代码,回落 8010。
///
public async Task ResolveDomainAsync(
string sourceCode,
long tenantId,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(sourceCode) || tenantId <= 0)
throw new InvalidOperationException("sourceCode/tenantId 非法");
// 验证租户在 sys_tenant 中存在且启用
var tenantExists = await _db.Ado.GetIntAsync(
"SELECT COUNT(1) FROM SysTenant WHERE Id = @TenantId AND Status = 1",
new List { new("@TenantId", tenantId) });
if (tenantExists <= 0)
throw new InvalidOperationException($"租户不存在或未启用:tenant={tenantId}");
// 优先从 GeneralizedCodeMaster 取公司代码,回落 8010
var domainRows = await _db.Ado.SqlQueryAsync(
"""
SELECT Domain
FROM GeneralizedCodeMaster
WHERE FldName='SystemConfig' AND Val='CompanyCode'
ORDER BY RecID LIMIT 1
""");
var domain = domainRows.FirstOrDefault()?.Domain;
return string.IsNullOrWhiteSpace(domain) ? "8010" : domain.Trim();
}
private sealed class MapRow
{
public long TenantId { get; set; }
}
private sealed class DomainRow
{
public string? Domain { get; set; }
}
}