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 ?? "") : "";
}