feat: Improve material ordering and default type in MCP tools

- Add SortOrder as secondary ordering key after Shape across all material
  queries (list_materials, search methods)
- Default material type to "Steel" when not specified in add_stock_with_offering

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-05 00:18:51 -05:00
parent 30071469bc
commit c795c129e5
3 changed files with 23 additions and 19 deletions

View File

@@ -117,6 +117,7 @@ public class InventoryTools
var materials = await query var materials = await query
.OrderBy(m => m.Shape) .OrderBy(m => m.Shape)
.ThenBy(m => m.SortOrder)
.ThenBy(m => m.Size) .ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
@@ -313,6 +314,7 @@ public class InventoryTools
return await query return await query
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Shape) .OrderBy(m => m.Shape)
.ThenBy(m => m.SortOrder)
.ThenBy(m => m.Size) .ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -322,7 +324,7 @@ public class InventoryTools
{ {
var flatBars = await SearchByDimension<FlatBarDimensions>(d => d.Width >= minValue && d.Width <= maxValue, shape); var flatBars = await SearchByDimension<FlatBarDimensions>(d => d.Width >= minValue && d.Width <= maxValue, shape);
var rectTubes = await SearchByDimension<RectangularTubeDimensions>(d => d.Width >= minValue && d.Width <= maxValue, shape); var rectTubes = await SearchByDimension<RectangularTubeDimensions>(d => d.Width >= minValue && d.Width <= maxValue, shape);
return flatBars.Concat(rectTubes).OrderBy(m => m.Shape).ThenBy(m => m.Size).ToList(); return flatBars.Concat(rectTubes).OrderBy(m => m.Shape).ThenBy(m => m.SortOrder).ThenBy(m => m.Size).ToList();
} }
// Height is used by RectangularTube, Channel, IBeam // Height is used by RectangularTube, Channel, IBeam
@@ -331,7 +333,7 @@ public class InventoryTools
var rectTubes = await SearchByDimension<RectangularTubeDimensions>(d => d.Height >= minValue && d.Height <= maxValue, shape); var rectTubes = await SearchByDimension<RectangularTubeDimensions>(d => d.Height >= minValue && d.Height <= maxValue, shape);
var channels = await SearchByDimension<ChannelDimensions>(d => d.Height >= minValue && d.Height <= maxValue, shape); var channels = await SearchByDimension<ChannelDimensions>(d => d.Height >= minValue && d.Height <= maxValue, shape);
var ibeams = await SearchByDimension<IBeamDimensions>(d => d.Height >= minValue && d.Height <= maxValue, shape); var ibeams = await SearchByDimension<IBeamDimensions>(d => d.Height >= minValue && d.Height <= maxValue, shape);
return rectTubes.Concat(channels).Concat(ibeams).OrderBy(m => m.Shape).ThenBy(m => m.Size).ToList(); return rectTubes.Concat(channels).Concat(ibeams).OrderBy(m => m.Shape).ThenBy(m => m.SortOrder).ThenBy(m => m.Size).ToList();
} }
// Size is used by SquareBar, SquareTube // Size is used by SquareBar, SquareTube
@@ -339,7 +341,7 @@ public class InventoryTools
{ {
var squareBars = await SearchByDimension<SquareBarDimensions>(d => d.Size >= minValue && d.Size <= maxValue, shape); var squareBars = await SearchByDimension<SquareBarDimensions>(d => d.Size >= minValue && d.Size <= maxValue, shape);
var squareTubes = await SearchByDimension<SquareTubeDimensions>(d => d.Size >= minValue && d.Size <= maxValue, shape); var squareTubes = await SearchByDimension<SquareTubeDimensions>(d => d.Size >= minValue && d.Size <= maxValue, shape);
return squareBars.Concat(squareTubes).OrderBy(m => m.Shape).ThenBy(m => m.Size).ToList(); return squareBars.Concat(squareTubes).OrderBy(m => m.Shape).ThenBy(m => m.SortOrder).ThenBy(m => m.Size).ToList();
} }
// Thickness is used by FlatBar, Angle // Thickness is used by FlatBar, Angle
@@ -347,7 +349,7 @@ public class InventoryTools
{ {
var flatBars = await SearchByDimension<FlatBarDimensions>(d => d.Thickness >= minValue && d.Thickness <= maxValue, shape); var flatBars = await SearchByDimension<FlatBarDimensions>(d => d.Thickness >= minValue && d.Thickness <= maxValue, shape);
var angles = await SearchByDimension<AngleDimensions>(d => d.Thickness >= minValue && d.Thickness <= maxValue, shape); var angles = await SearchByDimension<AngleDimensions>(d => d.Thickness >= minValue && d.Thickness <= maxValue, shape);
return flatBars.Concat(angles).OrderBy(m => m.Shape).ThenBy(m => m.Size).ToList(); return flatBars.Concat(angles).OrderBy(m => m.Shape).ThenBy(m => m.SortOrder).ThenBy(m => m.Size).ToList();
} }
// Wall is used by RoundTube, SquareTube, RectangularTube, Pipe // Wall is used by RoundTube, SquareTube, RectangularTube, Pipe
@@ -357,7 +359,7 @@ public class InventoryTools
var squareTubes = await SearchByDimension<SquareTubeDimensions>(d => d.Wall >= minValue && d.Wall <= maxValue, shape); var squareTubes = await SearchByDimension<SquareTubeDimensions>(d => d.Wall >= minValue && d.Wall <= maxValue, shape);
var rectTubes = await SearchByDimension<RectangularTubeDimensions>(d => d.Wall >= minValue && d.Wall <= maxValue, shape); var rectTubes = await SearchByDimension<RectangularTubeDimensions>(d => d.Wall >= minValue && d.Wall <= maxValue, shape);
var pipes = await SearchByDimension<PipeDimensions>(d => d.Wall != null && d.Wall >= minValue && d.Wall <= maxValue, shape); var pipes = await SearchByDimension<PipeDimensions>(d => d.Wall != null && d.Wall >= minValue && d.Wall <= maxValue, shape);
return roundTubes.Concat(squareTubes).Concat(rectTubes).Concat(pipes).OrderBy(m => m.Shape).ThenBy(m => m.Size).ToList(); return roundTubes.Concat(squareTubes).Concat(rectTubes).Concat(pipes).OrderBy(m => m.Shape).ThenBy(m => m.SortOrder).ThenBy(m => m.Size).ToList();
} }
private static MaterialDimensions? CreateDimensionsForShape( private static MaterialDimensions? CreateDimensionsForShape(
@@ -825,13 +827,14 @@ public class InventoryTools
}; };
} }
// Parse material type // Parse material type (default to Steel if not provided)
if (!Enum.TryParse<MaterialType>(type, ignoreCase: true, out var parsedType)) var typeValue = string.IsNullOrWhiteSpace(type) ? "Steel" : type;
if (!Enum.TryParse<MaterialType>(typeValue, ignoreCase: true, out var parsedType))
{ {
return new AddStockWithOfferingResult return new AddStockWithOfferingResult
{ {
Success = false, Success = false,
Error = $"Unknown material type: {type}. Valid types are: Steel, Aluminum, Stainless, Brass, Copper" Error = $"Unknown material type: {typeValue}. Valid types are: Steel, Aluminum, Stainless, Brass, Copper"
}; };
} }

View File

@@ -22,6 +22,7 @@ public class MaterialsController : ControllerBase
var materials = await _context.Materials var materials = await _context.Materials
.Where(m => m.IsActive) .Where(m => m.IsActive)
.OrderBy(m => m.Shape) .OrderBy(m => m.Shape)
.ThenBy(m => m.SortOrder)
.ThenBy(m => m.Size) .ThenBy(m => m.Size)
.Select(m => new MaterialDto .Select(m => new MaterialDto
{ {

View File

@@ -157,7 +157,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.Diameter >= minValue && d.Diameter <= maxValue) .Where(d => d.Diameter >= minValue && d.Diameter <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -174,7 +174,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.OuterDiameter >= minValue && d.OuterDiameter <= maxValue) .Where(d => d.OuterDiameter >= minValue && d.OuterDiameter <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -191,7 +191,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.Width >= minValue && d.Width <= maxValue) .Where(d => d.Width >= minValue && d.Width <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -208,7 +208,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.Size >= minValue && d.Size <= maxValue) .Where(d => d.Size >= minValue && d.Size <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -225,7 +225,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.Size >= minValue && d.Size <= maxValue) .Where(d => d.Size >= minValue && d.Size <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -242,7 +242,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.Width >= minValue && d.Width <= maxValue) .Where(d => d.Width >= minValue && d.Width <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -259,7 +259,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.Leg1 >= minValue && d.Leg1 <= maxValue) .Where(d => d.Leg1 >= minValue && d.Leg1 <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -276,7 +276,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.Height >= minValue && d.Height <= maxValue) .Where(d => d.Height >= minValue && d.Height <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -293,7 +293,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.Height >= minValue && d.Height <= maxValue) .Where(d => d.Height >= minValue && d.Height <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -310,7 +310,7 @@ public class MaterialService
.Where(d => d.Material.IsActive) .Where(d => d.Material.IsActive)
.Where(d => d.NominalSize >= minValue && d.NominalSize <= maxValue) .Where(d => d.NominalSize >= minValue && d.NominalSize <= maxValue)
.Select(d => d.Material) .Select(d => d.Material)
.OrderBy(m => m.Size) .OrderBy(m => m.SortOrder).ThenBy(m => m.Size)
.ToListAsync(); .ToListAsync();
} }
@@ -328,7 +328,7 @@ public class MaterialService
query = query.Where(m => m.IsActive); query = query.Where(m => m.IsActive);
} }
return await query.OrderBy(m => m.Size).ToListAsync(); return await query.OrderBy(m => m.SortOrder).ThenBy(m => m.Size).ToListAsync();
} }
/// <summary> /// <summary>