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>
This commit is contained in:
192
CutList.Web/Data/Entities/MaterialDimensions.cs
Normal file
192
CutList.Web/Data/Entities/MaterialDimensions.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user