namespace OpenNest.Data.MaterialLedger;
///
/// The body of MaterialLedger's GET /api/stock/opennest: the /api/stock shape plus
/// , false when ML has no approved mapping for the OpenNest material.
///
public sealed record LedgerStockResponse(
bool Mapped,
IReadOnlyList? Specs,
IReadOnlyList? Items);
///
/// Mirrors ML StockApi.OpenNestStockSpecDto. is the spec's place in ML's
/// acceptance rule (0 an exact mapping, 1 preferred, higher a substitute); an older ledger sends
/// neither it nor the catalog names, so they stay null and the spec counts as rank 1.
///
public sealed record LedgerStockSpec(long MaterialSpecId, string DisplayName, decimal ThicknessIn, string? GaugeLabel)
{
public int? Rank { get; init; }
public string? MaterialFamily { get; init; }
public string? Grade { get; init; }
public string? Finish { get; init; }
}
///
/// Mirrors ML StockApi.StockItemDto. Sizes are inches with the short
/// side; is free after active holds. and
/// stay strings so a new ML enum value still deserializes.
/// is its spec's rank, null from an older ledger.
///
public sealed record LedgerStockItem(
string ItemCode,
long MaterialSpecId,
string Kind,
decimal WidthIn,
decimal LengthIn,
int Quantity,
string Shape,
string LocationCode,
string LocationName,
string? ParentLocationCode,
decimal? CostPerUnit,
DateTime LastObservedAtUtc)
{
public int? Rank { get; init; }
}
/// ML InventoryItemKind names.
public static class LedgerItemKinds
{
public const string FullSheetBundle = "FullSheetBundle";
public const string FullSheet = "FullSheet";
public const string Drop = "Drop";
}
/// ML ShapeClassification names.
public static class LedgerItemShapes
{
public const string Rectangular = "Rectangular";
public const string IrregularConservativeRectangle = "IrregularConservativeRectangle";
public const string Unknown = "Unknown";
}
/// What a ledger stock request came to. Expected failures are results, never exceptions.
public abstract record LedgerStockResult
{
private LedgerStockResult() { }
/// No ledger URL is set on this PC.
public sealed record NotConfigured : LedgerStockResult;
/// The ledger did not answer usefully: network error, timeout, bad status or body.
public sealed record Unreachable(string Reason) : LedgerStockResult;
/// The ledger rejected the API key (401/403).
public sealed record Unauthorized : LedgerStockResult;
/// The ledger has no approved mapping for this material, grade and thickness.
public sealed record Unmapped : LedgerStockResult;
public sealed record Ok(IReadOnlyList Specs, IReadOnlyList Items) : LedgerStockResult;
}