| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- using Admin.NET.Plugin.AiDOP.DataPlatform;
- using Microsoft.Extensions.Logging;
- namespace Admin.NET.Plugin.AiDOP.Order;
- /// <summary>
- /// 从 165(DOPDEMORQ_SQLSERVER)批量读取实时可用库存。
- ///
- /// 只读、只查 InvMaster;连接经 MdpSourceScopeFactory 走 mdp_source 配置,不新开连接串。
- /// 口径与本库旧实现逐字对齐(跨全部 Location 求和、COALESCE(AvailStatusQty, QtyOnHand, 0)、
- /// 不过滤 IsActive),本包只换数据新鲜度,不动口径。
- /// 分块 IN 查询,避免逐物料跨库往返。
- /// </summary>
- public sealed class Mes165StockReader : ITransient
- {
- private const string SourceCode = "DOPDEMORQ_SQLSERVER";
- private readonly MdpSourceScopeFactory _scopeFactory;
- private readonly ILogger _logger;
- public Mes165StockReader(MdpSourceScopeFactory scopeFactory, ILoggerFactory loggerFactory)
- {
- _scopeFactory = scopeFactory;
- _logger = loggerFactory.CreateLogger(nameof(Mes165StockReader));
- }
- /// <summary>按物料号批量取可用库存;返回不含未命中的物料(调用方按 0 处理)。</summary>
- public async Task<Dictionary<string, decimal>> LoadAvailableQtyAsync(
- IReadOnlyList<string> itemNumbers,
- string domain,
- int batchSize = 500,
- CancellationToken ct = default)
- {
- var result = new Dictionary<string, decimal>(StringComparer.OrdinalIgnoreCase);
- if (itemNumbers.Count == 0)
- return result;
- var remote = await _scopeFactory.GetScopeAsync(SourceCode, ct);
- var size = batchSize <= 0 ? 500 : batchSize;
- for (var offset = 0; offset < itemNumbers.Count; offset += size)
- {
- ct.ThrowIfCancellationRequested();
- var chunk = itemNumbers.Skip(offset).Take(size).ToList();
- var names = new List<string>(chunk.Count);
- var pars = new List<SugarParameter> { new("@Domain", domain) };
- for (var i = 0; i < chunk.Count; i++)
- {
- names.Add($"@i{i}");
- pars.Add(new SugarParameter($"@i{i}", chunk[i]));
- }
- var sql =
- $"""
- SELECT ItemNum AS ItemNum,
- SUM(COALESCE(AvailStatusQty, QtyOnHand, 0)) AS Qty
- FROM InvMaster
- WHERE Domain = @Domain
- AND ItemNum IN ({string.Join(",", names)})
- GROUP BY ItemNum
- """;
- var rows = await remote.Ado.SqlQueryAsync<StockRow>(sql, pars);
- foreach (var r in rows)
- {
- if (string.IsNullOrWhiteSpace(r.ItemNum)) continue;
- result[r.ItemNum.Trim()] = r.Qty;
- }
- }
- _logger.LogInformation(
- "[Mes165StockReader] domain={Domain} requested={Requested} matched={Matched}",
- domain, itemNumbers.Count, result.Count);
- return result;
- }
- private sealed class StockRow
- {
- public string? ItemNum { get; set; }
- public decimal Qty { get; set; }
- }
- }
|