mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-26 22:01:06 -04:00
fix(server): report a nest's units with its sheet sizes
GET /api/nests/{id}/sheets returns sizes as stored, in the nest's units,
but did not say which. MaterialLedger compares them with inches, so a
millimeter nest's sheets never matched inventory. The response now carries
units (inches or millimeters), read the way NestReader reads them: absent
or unknown values are inches.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
be01124a0f
commit
548522775f
4 files changed
+60
-2
No files matched your search
@@ -10,6 +10,9 @@ public sealed class NestSheets
|
||||
|
||||
public int Revision { get; init; }
|
||||
|
||||
/// <summary>The nest's units, which every size in <see cref="Sheets"/> is stored in.</summary>
|
||||
public Units Units { get; init; }
|
||||
|
||||
/// <summary>One entry per distinct sheet size, ordered by width, then length.</summary>
|
||||
public IReadOnlyList<NestSheetSize> Sheets { get; init; } = Array.Empty<NestSheetSize>();
|
||||
|
||||
|
||||
@@ -236,6 +236,53 @@ public sealed class NestSheetsTests
|
||||
Assert.All(sheets.Plates.Skip(1), p => Assert.Null(p.ExpectedRemnant));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Units_AreTheNestsAndSizesStayAsStored()
|
||||
{
|
||||
using var factory = new ServerFactory();
|
||||
using var client = factory.CreateClient();
|
||||
var nest = NestApiTests.SyntheticNest();
|
||||
nest.Units = Units.Millimeters;
|
||||
var id = await Create(client, nest);
|
||||
|
||||
var json = await client.GetStringAsync($"/api/nests/{id}/sheets");
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
Assert.Equal("millimeters", document.RootElement.GetProperty("units").GetString());
|
||||
var sheets = JsonSerializer.Deserialize<NestSheets>(json, Options)!;
|
||||
Assert.Equal(Units.Millimeters, sheets.Units);
|
||||
Assert.Equal([(20.0, 30.0, 1)], Sizes(sheets));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InchNest_ReportsInches()
|
||||
{
|
||||
using var factory = new ServerFactory();
|
||||
using var client = factory.CreateClient();
|
||||
var nest = NestApiTests.SyntheticNest();
|
||||
nest.Units = Units.Inches;
|
||||
|
||||
var sheets = await Sheets(client, nest);
|
||||
|
||||
Assert.Equal(Units.Inches, sheets.Units);
|
||||
}
|
||||
|
||||
// NestReader keeps the default units when the field is absent or unrecognized.
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData("\"units\":\"furlongs\",")]
|
||||
public async Task AbsentOrUnknownUnits_AreInches(string unitsField)
|
||||
{
|
||||
using var factory = new ServerFactory();
|
||||
using var client = factory.CreateClient();
|
||||
var archive = TestNests.Zip("nest.json", "{" + unitsField + "\"drawings\":[],\"plates\":[]}");
|
||||
var id = await Create(client, archive);
|
||||
|
||||
var sheets = (await client.GetFromJsonAsync<NestSheets>($"/api/nests/{id}/sheets", Options))!;
|
||||
|
||||
Assert.Equal(Units.Inches, sheets.Units);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UnknownNest_Returns404()
|
||||
{
|
||||
|
||||
@@ -106,10 +106,14 @@ internal static class NestArchive
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// NestReader: absent or unknown units keep the nest default, inches.
|
||||
var units = Enum.TryParse<Units>(nest.Units, ignoreCase: true, out var parsed) ? parsed : Units.Inches;
|
||||
|
||||
sheets = new NestSheets
|
||||
{
|
||||
NestId = record.Id,
|
||||
Revision = record.Revision,
|
||||
Units = units,
|
||||
Sheets = sizes,
|
||||
Parts = parts,
|
||||
Plates = platesOut,
|
||||
@@ -178,6 +182,7 @@ internal static class NestArchive
|
||||
|
||||
private sealed class NestJson
|
||||
{
|
||||
public string? Units { get; set; }
|
||||
public double Thickness { get; set; }
|
||||
public MaterialJson? Material { get; set; } = new();
|
||||
public PlateDefaultsJson? PlateDefaults { get; set; }
|
||||
|
||||
@@ -126,8 +126,11 @@ Restore appends a new snapshot, never rewrites its source or intervening history
|
||||
|
||||
`/sheets` lists what a nest needs cut, for inventory holds (MaterialLedger). It
|
||||
skips the trailing empty new-plate slot, as `plateCount` does. Sheets group by
|
||||
size with `width` the shorter side, sizes as stored (unrounded), `quantity` the
|
||||
sum of those plates' quantities, ordered by width then length. `parts` has one
|
||||
size with `width` the shorter side, sizes as stored (unrounded, in the nest's
|
||||
`units`: `inches` or `millimeters`, inches when the archive has none or an
|
||||
unknown value, as `NestReader` reads it), `quantity` the sum of those plates'
|
||||
quantities, ordered by width then length. Callers that work in one unit, such
|
||||
as MaterialLedger's inches, must convert using `units`. `parts` has one
|
||||
entry per drawing, ordered by name: `required` is the drawing's required
|
||||
quantity, `nested` its parts on each plate times that plate's quantity; parts
|
||||
whose drawing is missing are skipped.
|
||||
|
||||
Reference in new issue
Block a user