feat(library): filter the drawing library by thickness, size, holes, date and customer

Finding a part on the nest server meant scrolling 40k drawings: the library
could only match an exact thickness or customer and knew nothing about a
drawing's size or holes. The library browser gets a Filter dialog with
inclusive ranges, and the query API takes them.

The server never parses packages and stays off IO, so the server worker now
measures each package beside its nest jobs (bounding sides, net area, closed
cutouts inside the outline) and stores the summary keyed by package hash
(schema v19). Identical geometry is measured once, an unreadable package is
recorded once instead of retried forever, and size or hole limits match only
measured drawings. Thickness ranges compare in inches across units and keep
the library's rule that a drawing saved without a thickness suits any.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ajandClaude Opus 5.5 committed 2026-11-12 16:47:51 -05:00
1 parent 1382d00496
commit b9fc618a50
38 files changed
+2170 -43

No files matched your search

+14 -1
View File
@@ -37,6 +37,16 @@ public sealed class DrawingLibraryQuery
public bool IncludeArchived { get; init; }
/// <summary>
/// Thickness, size, hole and saved-date ranges; <see cref="DrawingLibraryFilter.None"/>
/// means none. Its customer applies only when <see cref="Customer"/> is blank.
/// </summary>
public DrawingLibraryFilter Filter { get; init; } = DrawingLibraryFilter.None;
/// <summary>The customer matched: <see cref="Customer"/>, or the filter's when that is blank.</summary>
public string EffectiveCustomer =>
string.IsNullOrWhiteSpace(Customer) ? (Filter?.Customer ?? "") : Customer;
/// <summary>Column to order by; ties are broken by id in the same direction.</summary>
public DrawingSortField Sort { get; init; } = DrawingSortField.SavedAt;
@@ -59,6 +69,8 @@ public sealed class DrawingLibraryQuery
return "cutType must be Laser, Waterjet or Plasma.";
if (Thickness is { } thickness && (!double.IsFinite(thickness) || thickness < 0))
return "thickness must be a finite number, zero or greater.";
if (Filter is null)
return "filter must not be null.";
if (Offset < 0)
return "offset must be zero or greater.";
if (Limit < 1 || Limit > MaxLimit)
@@ -66,6 +78,7 @@ public sealed class DrawingLibraryQuery
return DrawingLibraryRules.TextError("search", NormalizedSearch, MaxSearchLength)
?? DrawingLibraryRules.TextError("customer", Customer ?? "", DrawingLibraryRules.MaxTextLength)
?? DrawingLibraryRules.TextError("materialName", MaterialName ?? "", DrawingLibraryRules.MaxTextLength)
?? DrawingLibraryRules.TextError("materialGrade", MaterialGrade ?? "", DrawingLibraryRules.MaxTextLength);
?? DrawingLibraryRules.TextError("materialGrade", MaterialGrade ?? "", DrawingLibraryRules.MaxTextLength)
?? Filter.GetValidationError();
}
}