namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting.Inventory; /// C5 前置守卫代码(LIVE pr_SFM_InventoryTransactionProcessing2 实核 9 道)。 public enum InventoryGuardCode { /// G1 进销存数据重复(基础数据 fan-out)。 DuplicateBaseData = 1, /// G2 物料无基础资料(ItemMaster)。 ItemMasterMissing = 2, /// G3 库位未维护(LocationMaster)。 LocationMasterMissing = 3, /// G4 物料_库位无库存(InvMaster)——净出库前置。 InvMasterMissing = 4, /// G5 物料_库位[_批次]无库存(LocationDetail)——净出库前置。 LocationDetailMissing = 5, /// G6 解冻数 > 冻结库存(inv-unfrz)。 UnfreezeExceedsFreeze = 6, /// G7 冻结数 > 非限制库存(inv-frz)。 FreezeExceedsAvail = 7, /// G8 质检过账数 > 质检库存(iss-tr-ins)——旧总结遗漏。 AssayIssueExceedsAssay = 8, /// G9 出库数 > 非限制库存(其它 TransType)。 IssueExceedsAvail = 9, } /// 单条守卫错误(结构化,非仅中文串;保留 LIVE ReturnMsg 语义供对账)。 public sealed class InventoryGuardError { public InventoryGuardCode Code { get; set; } public string Message { get; set; } public string ItemNum { get; set; } public string Location { get; set; } public string LotSerial { get; set; } } /// /// C5 库存上下文快照(守卫与写入的输入;由 store 加载,测试可 fake)。 /// 余额取自 DOP-L3(ado_inventory_master / ado_inventory_location_detail)变动前值; /// 存在性取自主数据(ItemMaster/LocationMaster,态①/②只读)。 /// public sealed class InventoryContext { public bool IsLotControl { get; set; } /// G1:加载时任一键 fan-out(一条命令匹配到多行基础数据)。 public bool HasDuplicateBaseData { get; set; } public HashSet Items { get; } = new(StringComparer.Ordinal); public HashSet Locations { get; } = new(StringComparer.Ordinal); /// InvMaster 变动前余额,键 = item|loc(存在性 = ContainsKey)。 public Dictionary InvMasters { get; } = new(StringComparer.Ordinal); /// LocationDetail 变动前余额,键 = item|loc|lot|refs。 public Dictionary LocationDetails { get; } = new(StringComparer.Ordinal); /// item → 当前默认库位(ItemMaster.Location 等价;空串/缺失=未落位)。 public Dictionary ItemDefaultLocation { get; } = new(StringComparer.Ordinal); public static string InvKey(string item, string loc) => (item ?? "") + "|" + (loc ?? ""); public static string DetailKey(string item, string loc, string lot, string refs) => (item ?? "") + "|" + (loc ?? "") + "|" + (lot ?? "") + "|" + (refs ?? ""); public bool ItemExists(string item) => Items.Contains(item ?? ""); public bool LocationExists(string loc) => Locations.Contains(loc ?? ""); public bool HasInvMaster(string item, string loc) => InvMasters.ContainsKey(InvKey(item, loc)); /// 取 InvMaster 变动前余额;缺失返回 null。 public InventoryBalance GetInvMaster(string item, string loc) => InvMasters.TryGetValue(InvKey(item, loc), out var b) ? b : null; /// 取 LocationDetail 变动前余额;缺失返回 null。 public InventoryBalance GetLocationDetail(string item, string loc, string lot, string refs) => LocationDetails.TryGetValue(DetailKey(item, loc, lot, refs), out var b) ? b : null; public string GetItemDefaultLocation(string item) => ItemDefaultLocation.TryGetValue(item ?? "", out var l) ? (l ?? "") : ""; }