using Admin.NET.Plugin.AiDOP.Infrastructure; using Admin.NET.Plugin.AiDOP.MaterialWarehouse.Dto; using Microsoft.Extensions.Options; namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse; /// /// S5 进出存查询:只读 mdp_std_inv_trans;响应带 historyFrom/asOf。 /// [ApiDescriptionSettings(Order = 303, Description = "进出存查询")] [Route("api/S5InoutQuery")] [NonUnify] public class InoutQueryService : IDynamicApiController, ITransient { private const long MainTenantId = 1300000000001L; private readonly ISqlSugarClient _db; private readonly UserManager _userManager; private readonly IInventoryTransactionReader _txReader; private readonly SourceDomainTenantResolver _domainTenant; private readonly AidopInventoryOptions _opt; public InoutQueryService( ISqlSugarClient db, UserManager userManager, IInventoryTransactionReader txReader, SourceDomainTenantResolver domainTenant, IOptions opt) { _db = db; _userManager = userManager; _txReader = txReader; _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}"); } } [DisplayName("进出存查询列表")] [HttpGet("list")] public async Task GetList([FromQuery] InoutQueryListInput input, CancellationToken ct) { var tenantId = ResolveTenantOrThrow(); var domain = await ResolveDomainOrThrowAsync(tenantId, ct); var page = await _txReader.QueryPageAsync(new InventoryTransactionQuery { TenantId = tenantId, Domain = domain, MaterialCode = input.MaterialCode, Location = input.Location, BatchNo = input.BatchNo, WorkOrderNo = input.WorkOrderNo, TransType = input.TransType, CreateTime = input.CreateTime, CreateUser = input.CreateUser, Page = input.Page, PageSize = input.PageSize }, ct); return new { total = page.Total, page = page.Page, pageSize = page.PageSize, list = page.List.Select(x => new InoutQueryListRow { TransTime = x.TransTime, MaterialCode = x.MaterialCode, MaterialName = x.MaterialName, Location = x.Location, LocationName = x.LocationName, BatchNo = x.BatchNo, BeginQty = x.BeginQty, InQty = x.InQty, OutQty = x.OutQty, EndQty = x.EndQty, Unit = x.Unit, TransType = x.TransType, WorkOrderNo = x.WorkOrderNo, DeliveryNo = x.DeliveryNo, DeliveryType = x.DeliveryType, Remark = x.Remark, CreateUser = x.CreateUser }).ToList(), asOf = page.AsOf, historyFrom = page.HistoryFrom, dataSource = InventoryDataSources.Std, isRealtime = false }; } [DisplayName("进出存查询货位选项")] [HttpGet("loc-options")] public async Task GetLocationOptions(CancellationToken ct) { var tenantId = ResolveTenantOrThrow(); var domain = await ResolveDomainOrThrowAsync(tenantId, ct); var list = await _db.Ado.SqlQueryAsync( """ SELECT location AS Val, descr AS Label FROM LocationMaster WHERE Domain = @Domain AND tenant_id = @TenantId AND IFNULL(location,'') <> '' ORDER BY location """, new List { new("@Domain", domain), new("@TenantId", tenantId) }); return list; } [DisplayName("进出存查询交易类型选项")] [HttpGet("transtype-options")] public async Task GetTransTypeOptions(CancellationToken ct) { var tenantId = ResolveTenantOrThrow(); var domain = await ResolveDomainOrThrowAsync(tenantId, ct); var list = await _db.Ado.SqlQueryAsync( """ SELECT Val AS Val, Comments AS Label FROM GeneralizedCodeMaster WHERE FldName = 'TransType' AND Domain = @Domain AND tenant_id = @TenantId AND IFNULL(Val,'') <> '' ORDER BY Val """, new List { new("@Domain", domain), new("@TenantId", tenantId) }); return list; } }