mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-28 20:41:06 -04:00
Auto Nest's Stock Options gets a Load from ledger button that reads the nest
material's free sheets and drops from MaterialLedger's API-key-protected
GET /api/stock/opennest. Ledger rows are request-local: the engine sees them as
ordinary NestPlateStock rows with ledger:{n} ids and finite quantities, and they
are never written to Nest.PlateOptions.
- OpenNest.Data/MaterialLedger: settings file, read-only client (X-Api-Key,
5 s timeout, closed LedgerStockResult set) and LedgerStockMapper (bundles and
sheets one row each, same-size drops grouped with ordered item codes, unknown
shapes and too-small items skipped, inch/mm conversion).
- Options: MaterialLedger URL and API key (DPAPI, CurrentUser) with Test.
- Auto Nest grid: Use, Qty and Source columns for every row; PlateOption gains
request-local Quantity and Id, which NestStockBuilder passes to the engine.
Ledger rows score by area; hand-typed costs stay saved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
2.5 KiB
C#
68 lines
2.5 KiB
C#
namespace OpenNest.Data.MaterialLedger;
|
|
|
|
/// <summary>
|
|
/// The body of MaterialLedger's <c>GET /api/stock/opennest</c>: the <c>/api/stock</c> shape plus
|
|
/// <see cref="Mapped"/>, false when ML has no approved mapping for the OpenNest material.
|
|
/// </summary>
|
|
public sealed record LedgerStockResponse(
|
|
bool Mapped,
|
|
IReadOnlyList<LedgerStockSpec>? Specs,
|
|
IReadOnlyList<LedgerStockItem>? Items);
|
|
|
|
public sealed record LedgerStockSpec(long MaterialSpecId, string DisplayName, decimal ThicknessIn, string? GaugeLabel);
|
|
|
|
/// <summary>
|
|
/// Mirrors ML <c>StockApi.StockItemDto</c>. Sizes are inches with <see cref="WidthIn"/> the short
|
|
/// side; <see cref="Quantity"/> is free after active holds. <see cref="Kind"/> and
|
|
/// <see cref="Shape"/> stay strings so a new ML enum value still deserializes.
|
|
/// </summary>
|
|
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);
|
|
|
|
/// <summary>ML <c>InventoryItemKind</c> names.</summary>
|
|
public static class LedgerItemKinds
|
|
{
|
|
public const string FullSheetBundle = "FullSheetBundle";
|
|
public const string FullSheet = "FullSheet";
|
|
public const string Drop = "Drop";
|
|
}
|
|
|
|
/// <summary>ML <c>ShapeClassification</c> names.</summary>
|
|
public static class LedgerItemShapes
|
|
{
|
|
public const string Rectangular = "Rectangular";
|
|
public const string IrregularConservativeRectangle = "IrregularConservativeRectangle";
|
|
public const string Unknown = "Unknown";
|
|
}
|
|
|
|
/// <summary>What a ledger stock request came to. Expected failures are results, never exceptions.</summary>
|
|
public abstract record LedgerStockResult
|
|
{
|
|
private LedgerStockResult() { }
|
|
|
|
/// <summary>No ledger URL is set on this PC.</summary>
|
|
public sealed record NotConfigured : LedgerStockResult;
|
|
|
|
/// <summary>The ledger did not answer usefully: network error, timeout, bad status or body.</summary>
|
|
public sealed record Unreachable(string Reason) : LedgerStockResult;
|
|
|
|
/// <summary>The ledger rejected the API key (401/403).</summary>
|
|
public sealed record Unauthorized : LedgerStockResult;
|
|
|
|
/// <summary>The ledger has no approved mapping for this material, grade and thickness.</summary>
|
|
public sealed record Unmapped : LedgerStockResult;
|
|
|
|
public sealed record Ok(IReadOnlyList<LedgerStockSpec> Specs, IReadOnlyList<LedgerStockItem> Items) : LedgerStockResult;
|
|
}
|