Files
OpenNest/OpenNest.IO/Bom/BomPartRow.cs
T
aj b83aeb0e41 fix(bom): find the drawing for rows that still need a thickness
A BOM row with a file name and a matching drawing but a blank thickness
was reported "No DXF" and locked, so its thickness could not be entered
and the part was dropped: BomAnalyzer skips such items before looking
for a drawing, and the form only knew drawings the analyzer matched.
A row with a blank material read "Matched" but was silently left out
of every group.

Rows now resolve their drawing through a DrawingFileIndex shared with
BomAnalyzer (whose behavior and tests are unchanged), and a row's status
is computed from its values:

  Ready | Needs material | Needs thickness | No drawing found | No file name

Rows with a drawing stay editable, and an edit updates the status cell.
Groups take only Ready rows (a zero, negative or non-finite thickness is
not Ready). The summary line counts ready rows and each problem.

Build_RowWithoutThickness_StillFindsItsDrawing failed at its DxfPath
assertion against the previous commit. Mutation reds: removing the
material check, accepting zero or non-finite thickness, skipping the
drawing for rows without thickness, and grouping without the status
each fail the Bom tests.

Project Memory: b8e3a978-2cfe-4fe7-b2a5-eb01c6c54679
2026-10-05 17:50:54 -04:00

81 lines
2.5 KiB
C#

using System;
namespace OpenNest.IO.Bom;
/// <summary>Whether a BOM row can be imported, and if not, why.</summary>
public enum BomRowStatus
{
/// <summary>Drawing found, material and thickness set: the row is imported.</summary>
Ready,
/// <summary>Drawing found but the material is blank.</summary>
NeedsMaterial,
/// <summary>Drawing found but the thickness is blank, zero or negative.</summary>
NeedsThickness,
/// <summary>No drawing file matches the row's file name.</summary>
NoDrawing,
/// <summary>The BOM row has no file name.</summary>
NoFileName,
}
/// <summary>
/// One BOM line as the import dialog shows and edits it: the values read
/// from the BOM, the drawing file it resolved to and whether it can be
/// imported.
/// </summary>
public class BomPartRow
{
public int? ItemNum { get; set; }
public string FileName { get; set; }
public int? Qty { get; set; }
public string Description { get; set; }
public string Material { get; set; }
public double? Thickness { get; set; }
/// <summary>The matched drawing file, or null when none was found.</summary>
public string DxfPath { get; set; }
public BomRowStatus Status
{
get
{
if (string.IsNullOrWhiteSpace(FileName))
return BomRowStatus.NoFileName;
if (string.IsNullOrWhiteSpace(DxfPath))
return BomRowStatus.NoDrawing;
if (string.IsNullOrWhiteSpace(Material))
return BomRowStatus.NeedsMaterial;
if (Thickness is not double thickness || !double.IsFinite(thickness) || thickness <= 0)
return BomRowStatus.NeedsThickness;
return BomRowStatus.Ready;
}
}
public string StatusText => Describe(Status);
/// <summary>
/// True when the row has a drawing, so the operator can complete its
/// values; rows without one can never be imported.
/// </summary>
public bool IsEditable => Status is not (BomRowStatus.NoFileName or BomRowStatus.NoDrawing);
public static string Describe(BomRowStatus status) =>
status switch
{
BomRowStatus.Ready => "Ready",
BomRowStatus.NeedsMaterial => "Needs material",
BomRowStatus.NeedsThickness => "Needs thickness",
BomRowStatus.NoDrawing => "No drawing found",
BomRowStatus.NoFileName => "No file name",
_ => throw new ArgumentOutOfRangeException(nameof(status), status, null),
};
}