mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 07:11:06 -04:00
A release can now cover several sets, each with its own kit count, so parts
from different kits share sheets. It can also merge into an existing draft
nest instead of always creating one. Schema v9 replaces the single-set
release tables: releases, their set lines, their nests (created or merged,
with the nest revision before and after) and the drawing quantities each set
added to each nest, so a kit stays traceable once kits share a nest. The v8
migration turns each existing release into one set line with created nests.
Undo runs on the server in one transaction: created nests are soft-deleted
and merged nests restored to their pre-merge revision, but only while each
still holds what the release wrote. Otherwise nothing changes and the
changed nests are listed, so the operator can skip them. A nest restored to
that revision counts as unchanged, which lets releases sharing a nest be
undone newest first.
The old /api/sets/{id}/releases and /api/nests/{id}/release routes are
replaced by /api/releases; no tagged desktop used them. The desktop still
releases one set at a time until the release dialog is reworked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
101 lines
4.1 KiB
C#
101 lines
4.1 KiB
C#
using OpenNest.Data;
|
||
using OpenNest.Geometry;
|
||
|
||
namespace OpenNest.Tests.Data;
|
||
|
||
public class SetReleaseTextTests
|
||
{
|
||
private static SetReleaseNest Nest(NestStatus status, bool deleted = false, bool joined = true) => new()
|
||
{
|
||
NestId = Guid.NewGuid(),
|
||
MaterialName = "Synthetic Steel",
|
||
MaterialGrade = "Grade A",
|
||
Thickness = 0.25,
|
||
Units = Units.Inches,
|
||
CutType = CutType.Waterjet,
|
||
Nest = joined ? new NestRecord { Name = "N1", Status = status, Deleted = deleted } : null,
|
||
};
|
||
|
||
[Fact]
|
||
public void Progress_CountsCutNestsAndLeavesDeletedOnesOut()
|
||
{
|
||
Assert.Equal("2 of 3 cut", SetReleaseText.Progress(new SetReleaseRecord
|
||
{
|
||
Nests = new[] { Nest(NestStatus.HasBeenCut), Nest(NestStatus.HasBeenCut), Nest(NestStatus.Draft) },
|
||
}));
|
||
Assert.Equal("0 of 1 cut, 2 deleted", SetReleaseText.Progress(new SetReleaseRecord
|
||
{
|
||
Nests = new[] { Nest(NestStatus.ToBeCut), Nest(NestStatus.HasBeenCut, deleted: true), Nest(NestStatus.Quote, joined: false) },
|
||
}));
|
||
Assert.Equal("All nests deleted", SetReleaseText.Progress(new SetReleaseRecord
|
||
{
|
||
Nests = new[] { Nest(NestStatus.Draft, deleted: true), Nest(NestStatus.Draft, deleted: true) },
|
||
}));
|
||
}
|
||
|
||
[Fact]
|
||
public void NestState_AndGroup_DescribeOneNest()
|
||
{
|
||
Assert.Equal("To Be Cut", SetReleaseText.NestState(Nest(NestStatus.ToBeCut)));
|
||
Assert.Equal("Deleted", SetReleaseText.NestState(Nest(NestStatus.ToBeCut, deleted: true)));
|
||
Assert.Equal("Synthetic Steel Grade A 0.25 in waterjet", SetReleaseText.Group(Nest(NestStatus.Draft)));
|
||
}
|
||
|
||
[Fact]
|
||
public void Origin_NamesTheSetRevisionMultiplierAndWho()
|
||
{
|
||
var text = SetReleaseText.Origin(new SetReleaseRecord
|
||
{
|
||
Sets = new[] { new SetReleaseLine { SetName = "Synthetic kit", SetRevision = 3, Quantity = 2 } },
|
||
ReleasedBy = "Synthetic operator",
|
||
});
|
||
|
||
Assert.Equal("Released from set 'Synthetic kit' revision 3 ×2 by Synthetic operator", text);
|
||
}
|
||
|
||
[Fact]
|
||
public void Origin_OfAMergeOfSeveralSets_NamesThemAll_AndAnUndo()
|
||
{
|
||
var nest = Guid.NewGuid();
|
||
var release = new SetReleaseRecord
|
||
{
|
||
Sets = new[]
|
||
{
|
||
new SetReleaseLine { SetName = "Kit A", SetRevision = 3, Quantity = 2 },
|
||
new SetReleaseLine { SetName = "Kit B", SetRevision = 1, Quantity = 1 },
|
||
new SetReleaseLine { SetName = "Kit C", SetRevision = 5, Quantity = 4 },
|
||
},
|
||
Nests = new[] { new SetReleaseNest { NestId = nest, Kind = SetReleaseNestKind.Merged } },
|
||
UndoneAt = new DateTime(2026, 10, 21, 9, 0, 0, DateTimeKind.Utc),
|
||
};
|
||
|
||
Assert.Equal("Merged from sets 'Kit A' revision 3 ×2, 'Kit B' revision 1 ×1 and 'Kit C' revision 5 ×4 (undone)",
|
||
SetReleaseText.Origin(release, nest));
|
||
Assert.StartsWith("Released from sets", SetReleaseText.Origin(release));
|
||
Assert.Equal("Undone", SetReleaseText.Progress(release));
|
||
}
|
||
|
||
[Fact]
|
||
public void NestDefaults_ConvertedTo_ScalesPlateDefaultsBetweenUnits()
|
||
{
|
||
var inches = new NestDefaults
|
||
{
|
||
Units = Units.Inches,
|
||
Size = new Size(60, 120),
|
||
Quadrant = 3,
|
||
PartSpacing = 0.125,
|
||
EdgeSpacing = new Spacing(0.5, 0.25, 0.5, 0.25),
|
||
};
|
||
|
||
var millimeters = inches.ConvertedTo(Units.Millimeters);
|
||
var back = millimeters.ConvertedTo(Units.Inches);
|
||
|
||
Assert.Equal((Units.Millimeters, 1524.0, 3048.0, 3, 3.175), (millimeters.Units, millimeters.Size.Width,
|
||
millimeters.Size.Length, millimeters.Quadrant, millimeters.PartSpacing));
|
||
Assert.Equal((12.7, 6.35, 12.7, 6.35), (millimeters.EdgeSpacing.Left, millimeters.EdgeSpacing.Bottom,
|
||
millimeters.EdgeSpacing.Right, millimeters.EdgeSpacing.Top));
|
||
Assert.Equal((60.0, 120.0, 0.125), (back.Size.Width, back.Size.Length, back.PartSpacing));
|
||
Assert.NotSame(inches, inches.ConvertedTo(Units.Inches));
|
||
}
|
||
}
|