mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-07 04:15:43 -05: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>
59 lines
2.2 KiB
C#
59 lines
2.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using OpenNest.Engine.Jobs.Adapters;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.Engine.Jobs;
|
|
|
|
/// <summary>
|
|
/// Shared stock snapshots for whole-job front ends. Plate repeat count is not inventory; an
|
|
/// option's own quantity and id win over <c>quantityPerOption</c> and its position.
|
|
/// </summary>
|
|
public static class NestStockBuilder
|
|
{
|
|
public static IReadOnlyList<NestPlateStock> FromTemplate(
|
|
Plate template,
|
|
IReadOnlyList<PlateOption> options,
|
|
int? quantityPerOption = null
|
|
)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(template);
|
|
if (options == null || options.Count == 0)
|
|
return new[] { DrawingJobMapper.FromPlate("plate", template, quantityPerOption) };
|
|
|
|
var stock = new List<NestPlateStock>(options.Count);
|
|
for (var i = 0; i < options.Count; i++)
|
|
{
|
|
var option = options[i];
|
|
ArgumentNullException.ThrowIfNull(option);
|
|
var size = new Size(option.Width, option.Length);
|
|
stock.Add(new NestPlateStock(
|
|
option.Id ?? $"option-{i}",
|
|
size,
|
|
option.Quantity ?? quantityPerOption,
|
|
template.PartSpacing,
|
|
template.EdgeSpacing,
|
|
template.Quadrant,
|
|
option.Cost == 0 ? null : option.Cost,
|
|
ClampZonesFor(template, size)
|
|
)
|
|
{ ClampRail = template.ClampRail });
|
|
}
|
|
NestJobValidator.ValidateStockCosts(stock);
|
|
return stock.AsReadOnly();
|
|
}
|
|
|
|
/// <summary>
|
|
/// A template following the machine clamp rail offers each sheet size with the rail
|
|
/// resolved for that size (clamps are fixed to the machine, not the sheet); explicit
|
|
/// template zones are offered unchanged.
|
|
/// </summary>
|
|
private static IReadOnlyList<ClampZone> ClampZonesFor(Plate template, Size size) =>
|
|
template.ClampRail?.ResolveFor(size, template.Quadrant)
|
|
?? new List<ClampZone>(template.ClampZones);
|
|
|
|
/// <summary>Single-sheet callers may not silently create additional sheets.</summary>
|
|
public static IReadOnlyList<NestPlateStock> SinglePlate(Plate plate) =>
|
|
FromTemplate(plate, null, quantityPerOption: 1);
|
|
}
|