mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-12 20:31:10 -05:00
feat(reporting): name the thickness on part printouts
The nest report already leads its thickness with the machine config's Name / Gauge; the part printout's THICKNESS cell now does the same (16 ga - 0.0598"), from the same lookup in the desktop. Thickness names are typed into the machine config, so both writers now check them against the bundled font's Latin-1 limit like other free text, instead of failing partway through rendering. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2f3f105a5e
commit
72e16139ae
6 files changed
+65
-6
No files matched your search
@@ -103,6 +103,7 @@ public static class NestPdfWriter
|
||||
ReportFonts.ValidateText(snapshot.Notes, "Notes");
|
||||
ReportFonts.ValidateText(snapshot.Material, "Material");
|
||||
ReportFonts.ValidateText(snapshot.Grade, "Material grade");
|
||||
ReportFonts.ValidateText(snapshot.ThicknessName, "Thickness name");
|
||||
foreach (var drawing in snapshot.Drawings)
|
||||
ReportFonts.ValidateText(drawing.Name, $"Drawing {drawing.Id} name");
|
||||
}
|
||||
|
||||
@@ -20,6 +20,12 @@ public sealed record PrintoutPart(string Name, string Customer, double Width, do
|
||||
public sealed record PartPrintoutSnapshot(string Title, string Material, double Thickness, string Units,
|
||||
DateTimeOffset GeneratedAt, ImmutableArray<PrintoutPart> Parts)
|
||||
{
|
||||
/// <summary>
|
||||
/// The name the nest machine's config gives this thickness ("16 ga"), shown before the
|
||||
/// decimal; empty when it has none. The caller supplies it, as for the nest report.
|
||||
/// </summary>
|
||||
public string ThicknessName { get; init; } = "";
|
||||
|
||||
/// <summary>"lb" for inch jobs, "kg" for millimeter jobs.</summary>
|
||||
public string WeightUnits => Units == "mm" ? "kg" : "lb";
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ public static class PartPrintoutWriter
|
||||
{
|
||||
ReportFonts.ValidateText(snapshot.Title, "Printout title");
|
||||
ReportFonts.ValidateText(snapshot.Material, "Material");
|
||||
ReportFonts.ValidateText(snapshot.ThicknessName, "Thickness name");
|
||||
foreach (var part in snapshot.Parts)
|
||||
{
|
||||
ReportFonts.ValidateText(part.Name, $"Drawing '{part.Name}' name");
|
||||
@@ -99,7 +100,7 @@ public static class PartPrintoutWriter
|
||||
var rows = new (string, string, string, string)[]
|
||||
{
|
||||
("DIMENSIONS", $"{Length(part.Width, units)} x {Length(part.Length, units)}", "MATERIAL", Dash(snapshot.Material)),
|
||||
("THICKNESS", snapshot.Thickness > 0 ? Length(snapshot.Thickness, units, "0.####") : "-",
|
||||
("THICKNESS", Thickness(snapshot),
|
||||
"CUT LENGTH", Length(part.CutLength, units)),
|
||||
("PIERCE COUNT", part.PierceCount.ToString(Invariant), "WEIGHT",
|
||||
part.Weight is { } weight ? $"{Number(weight)} {snapshot.WeightUnits}" : "-"),
|
||||
@@ -177,6 +178,15 @@ public static class PartPrintoutWriter
|
||||
private static string Length(double value, string units, string format = "0.00") =>
|
||||
units == "mm" ? $"{value.ToString(format, Invariant)} mm" : $"{value.ToString(format, Invariant)}\"";
|
||||
|
||||
/// <summary>The machine config's name for the thickness leads: 16 ga - 0.0598".</summary>
|
||||
private static string Thickness(PartPrintoutSnapshot snapshot)
|
||||
{
|
||||
if (snapshot.Thickness <= 0)
|
||||
return "-";
|
||||
var value = Length(snapshot.Thickness, snapshot.Units, "0.####");
|
||||
return snapshot.ThicknessName.Length > 0 ? $"{snapshot.ThicknessName} - {value}" : value;
|
||||
}
|
||||
|
||||
private static string Number(double value) => value.ToString("0.00", Invariant);
|
||||
|
||||
private static string Dash(string text) => string.IsNullOrWhiteSpace(text) ? "-" : text.Trim();
|
||||
|
||||
@@ -122,6 +122,40 @@ public sealed class PartPrintoutTests : IDisposable
|
||||
Assert.Contains("Generated 9/29/2026 12:00 PM", text);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void Write_NamedThicknessLeadsTheDecimal()
|
||||
{
|
||||
var nest = NestReportTestData.CreateNest();
|
||||
var bracket = nest.Drawings.Single(drawing => drawing.Name == "Bracket");
|
||||
var path = Path.Combine(directory, "named.pdf");
|
||||
|
||||
PartPrintoutWriter.Write(PartPrintoutBuilder.Capture(nest, [bracket], NestReportTestData.GeneratedAt)
|
||||
with
|
||||
{ ThicknessName = "11 ga" }, path);
|
||||
|
||||
Assert.Matches(@"THICKNESS\s+11 ga - 0\.125""\s+CUT LENGTH", ReportPdf.Text(path, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Write_RejectsAThicknessNameTheBundledFontCannotShow()
|
||||
{
|
||||
var nest = NestReportTestData.CreateNest();
|
||||
var printout = Path.Combine(directory, "bad-printout.pdf");
|
||||
var report = Path.Combine(directory, "bad-report.pdf");
|
||||
|
||||
var printoutError = Assert.Throws<InvalidOperationException>(() => PartPrintoutWriter.Write(
|
||||
PartPrintoutBuilder.Capture(nest, null, NestReportTestData.GeneratedAt) with { ThicknessName = "1/4—plate" },
|
||||
printout));
|
||||
var reportError = Assert.Throws<InvalidOperationException>(() => NestPdfWriter.Write(
|
||||
NestReportBuilder.Capture(nest, NestReportTestData.GeneratedAt) with { ThicknessName = "1/4—plate" },
|
||||
report));
|
||||
|
||||
Assert.Contains("Thickness name", printoutError.Message);
|
||||
Assert.Contains("Thickness name", reportError.Message);
|
||||
Assert.False(File.Exists(printout));
|
||||
Assert.False(File.Exists(report));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Write_RejectsTextTheBundledFontCannotShow()
|
||||
{
|
||||
|
||||
@@ -862,12 +862,15 @@ namespace OpenNest.Forms
|
||||
catalogDensity
|
||||
) with
|
||||
{
|
||||
// The name the machine config gives the nest's thickness ("16 ga"), if any.
|
||||
ThicknessName = Data.MachineCuttingDefaults.Find(machine, targets.Nest)?.Name?.Trim() ?? "",
|
||||
ThicknessName = MachineThicknessName(machine, targets.Nest),
|
||||
};
|
||||
NestPdfWriter.Write(snapshot, destination);
|
||||
}
|
||||
|
||||
/// <summary>The name the machine config gives the nest's thickness ("16 ga"), or empty.</summary>
|
||||
private static string MachineThicknessName(Data.MachineConfig machine, Nest nest) =>
|
||||
Data.MachineCuttingDefaults.Find(machine, nest)?.Name?.Trim() ?? "";
|
||||
|
||||
/// <summary>
|
||||
/// Writes one printout page per drawing, in order. Capture is synchronous on the UI thread
|
||||
/// and reads only drawings, so it has no accounting or dirty-state side effects.
|
||||
@@ -877,13 +880,17 @@ namespace OpenNest.Forms
|
||||
ArgumentNullException.ThrowIfNull(drawings);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(destination);
|
||||
var material = Nest.Material;
|
||||
var machine = MachineSettings.FindMachine(Nest.Machine);
|
||||
var catalogDensity = Data.MaterialDensityLookup.Resolve(
|
||||
material?.Name,
|
||||
material?.Grade,
|
||||
MachineSettings.FindMachine(Nest.Machine),
|
||||
machine,
|
||||
MachineSettings.LoadMaterials()
|
||||
);
|
||||
var snapshot = PartPrintoutBuilder.Capture(Nest, drawings, DateTimeOffset.Now, catalogDensity);
|
||||
var snapshot = PartPrintoutBuilder.Capture(Nest, drawings, DateTimeOffset.Now, catalogDensity) with
|
||||
{
|
||||
ThicknessName = MachineThicknessName(machine, Nest),
|
||||
};
|
||||
PartPrintoutWriter.Write(snapshot, destination);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ suggesting `<nest-name>.printout.pdf` or `<drawing-name>.printout.pdf`. Each par
|
||||
gets one Letter portrait page, bookmarked by name, with the name and customer (the drawing's, else the
|
||||
nest's) as the header, the part's material contours stroked to fit (leads, rapids
|
||||
and marks omitted), a details table and the generated time. The table shows the
|
||||
bounding box (Y extent x X extent), nest material and thickness, cut length and
|
||||
bounding box (Y extent x X extent), nest material and thickness (led by the
|
||||
machine config's thickness name, as in the nest report), cut length and
|
||||
pierce count, net area, weight
|
||||
(the nest report's density rules) and required quantity. Cut length sums the moves the head cuts (cut, break, common-line and lead layers); each run of
|
||||
them is one pierce, so scribe marks, tab spans, display moves and a display
|
||||
|
||||
Reference in new issue
Block a user