Files
CutList/CutList.Web/Data/Entities/MaterialDimensions.cs
AJ Isaacs 4f6d986dc9 feat: Add material dimensions with typed properties
Implement TPH inheritance for material dimensions:
- MaterialShape enum with display names and parsing
- MaterialType enum (Steel, Aluminum, Stainless, etc.)
- MaterialDimensions base class with derived types per shape
- Auto-generate size strings from typed dimensions
- SortOrder field for numeric dimension sorting

Each shape has specific dimension properties:
- RoundBar: Diameter
- RoundTube: OuterDiameter, Wall
- FlatBar: Width, Thickness
- SquareBar/Tube: Size, Wall
- RectangularTube: Width, Height, Wall
- Angle: Leg1, Leg2, Thickness
- Channel: Height, Flange, Web
- IBeam: Height, WeightPerFoot
- Pipe: NominalSize, Wall, Schedule

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 23:37:43 -05:00

193 lines
6.0 KiB
C#

namespace CutList.Web.Data.Entities;
/// <summary>
/// Base class for material dimensions. Each shape has its own derived class with specific properties.
/// </summary>
public abstract class MaterialDimensions
{
public int Id { get; set; }
public int MaterialId { get; set; }
public Material Material { get; set; } = null!;
/// <summary>
/// Generates a display string for the size based on the dimensions.
/// </summary>
public abstract string GenerateSizeString();
/// <summary>
/// Gets the primary dimension value for sorting (in thousandths of an inch).
/// </summary>
public abstract int GetSortOrder();
}
/// <summary>
/// Dimensions for Round Bar: solid round stock.
/// </summary>
public class RoundBarDimensions : MaterialDimensions
{
public decimal Diameter { get; set; }
public override string GenerateSizeString() =>
FormatDimension(Diameter);
public override int GetSortOrder() => (int)(Diameter * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}
/// <summary>
/// Dimensions for Round Tube: hollow round stock.
/// </summary>
public class RoundTubeDimensions : MaterialDimensions
{
public decimal OuterDiameter { get; set; }
public decimal Wall { get; set; }
public override string GenerateSizeString() =>
$"{FormatDimension(OuterDiameter)} OD x {FormatDimension(Wall)} wall";
public override int GetSortOrder() => (int)(OuterDiameter * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}
/// <summary>
/// Dimensions for Flat Bar: rectangular solid stock.
/// </summary>
public class FlatBarDimensions : MaterialDimensions
{
public decimal Width { get; set; }
public decimal Thickness { get; set; }
public override string GenerateSizeString() =>
$"{FormatDimension(Width)} x {FormatDimension(Thickness)}";
public override int GetSortOrder() => (int)(Width * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}
/// <summary>
/// Dimensions for Square Bar: solid square stock.
/// </summary>
public class SquareBarDimensions : MaterialDimensions
{
public decimal Size { get; set; }
public override string GenerateSizeString() =>
FormatDimension(Size);
public override int GetSortOrder() => (int)(Size * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}
/// <summary>
/// Dimensions for Square Tube: hollow square stock.
/// </summary>
public class SquareTubeDimensions : MaterialDimensions
{
public decimal Size { get; set; }
public decimal Wall { get; set; }
public override string GenerateSizeString() =>
$"{FormatDimension(Size)} x {FormatDimension(Wall)} wall";
public override int GetSortOrder() => (int)(Size * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}
/// <summary>
/// Dimensions for Rectangular Tube: hollow rectangular stock.
/// </summary>
public class RectangularTubeDimensions : MaterialDimensions
{
public decimal Width { get; set; }
public decimal Height { get; set; }
public decimal Wall { get; set; }
public override string GenerateSizeString() =>
$"{FormatDimension(Width)} x {FormatDimension(Height)} x {FormatDimension(Wall)} wall";
public override int GetSortOrder() => (int)(Width * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}
/// <summary>
/// Dimensions for Angle: L-shaped stock.
/// </summary>
public class AngleDimensions : MaterialDimensions
{
public decimal Leg1 { get; set; }
public decimal Leg2 { get; set; }
public decimal Thickness { get; set; }
public override string GenerateSizeString() =>
$"{FormatDimension(Leg1)} x {FormatDimension(Leg2)} x {FormatDimension(Thickness)}";
public override int GetSortOrder() => (int)(Leg1 * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}
/// <summary>
/// Dimensions for Channel: C-shaped stock.
/// </summary>
public class ChannelDimensions : MaterialDimensions
{
public decimal Height { get; set; }
public decimal Flange { get; set; }
public decimal Web { get; set; }
public override string GenerateSizeString() =>
$"{FormatDimension(Height)} x {FormatDimension(Flange)} x {FormatDimension(Web)}";
public override int GetSortOrder() => (int)(Height * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}
/// <summary>
/// Dimensions for I-Beam: wide flange beam.
/// </summary>
public class IBeamDimensions : MaterialDimensions
{
public decimal Height { get; set; }
public decimal WeightPerFoot { get; set; }
public override string GenerateSizeString() =>
$"W{Height:0.##} x {WeightPerFoot:0.##}";
public override int GetSortOrder() => (int)(Height * 1000);
}
/// <summary>
/// Dimensions for Pipe: nominal pipe size.
/// </summary>
public class PipeDimensions : MaterialDimensions
{
public decimal NominalSize { get; set; }
public decimal? Wall { get; set; }
public string? Schedule { get; set; }
public override string GenerateSizeString() =>
!string.IsNullOrEmpty(Schedule)
? $"{FormatDimension(NominalSize)} NPS Sch {Schedule}"
: $"{FormatDimension(NominalSize)} NPS x {FormatDimension(Wall ?? 0)} wall";
public override int GetSortOrder() => (int)(NominalSize * 1000);
private static string FormatDimension(decimal value) =>
CutList.Core.Formatting.ArchUnits.FormatFromInches((double)value);
}