using Admin.NET.Plugin.AiDOP.Infrastructure;
using Admin.NET.Plugin.AiDOP.MaterialWarehouse.Dto;
using Microsoft.Extensions.Options;
namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse;
///
/// S5 库存查询:经 IInventoryBalanceReader,优先 LIVE_165,回落 mdp_std_inventory。
/// Domain 由 SourceDomainTenantResolver 反查,禁止回落 8010。
///
[ApiDescriptionSettings(Order = 300, Description = "库存查询")]
[Route("api/S5StockQuery")]
[NonUnify]
public class StockQueryService : IDynamicApiController, ITransient
{
private const long MainTenantId = 1300000000001L;
private readonly ISqlSugarClient _db;
private readonly UserManager _userManager;
private readonly IInventoryBalanceReader _balanceReader;
private readonly SourceDomainTenantResolver _domainTenant;
private readonly AidopInventoryOptions _opt;
public StockQueryService(
ISqlSugarClient db,
UserManager userManager,
IInventoryBalanceReader balanceReader,
SourceDomainTenantResolver domainTenant,
IOptions opt)
{
_db = db;
_userManager = userManager;
_balanceReader = balanceReader;
_domainTenant = domainTenant;
_opt = opt.Value;
}
private long ResolveTenantOrThrow()
{
var tid = _userManager.TenantId;
if (tid <= 0)
throw Oops.Oh("无法确定当前租户,请重新登录或选择目标租户");
if (_userManager.SuperAdmin && tid == MainTenantId)
throw Oops.Oh("超级管理员操作前必须选择目标租户");
return tid;
}
private async Task ResolveDomainOrThrowAsync(long tenantId, CancellationToken ct = default)
{
var sourceCode = string.IsNullOrWhiteSpace(_opt.SourceCode) ? "DOPDEMORQ_SQLSERVER" : _opt.SourceCode.Trim();
try
{
return await _domainTenant.ResolveDomainAsync(sourceCode, tenantId, ct);
}
catch (Exception ex)
{
throw Oops.Oh($"无法解析当前租户 Domain 映射:{ex.Message}");
}
}
private const string LocTypeExpr = "CASE WHEN t.typed='VMI' THEN 'VMI' WHEN t.typed='Supp' THEN 'O库' ELSE '' END";
[DisplayName("库存查询列表")]
[HttpGet("list")]
public async Task