feat: Add full REST API with controllers, DTOs, and service layer

Add controllers for suppliers, stock items, jobs, cutting tools, and
packing. Refactor MaterialsController to use MaterialService with
dimension-aware CRUD, search, and bulk operations. Extract DTOs into
dedicated files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-05 16:53:53 -05:00
parent 21d50e7c20
commit 17f16901ef
13 changed files with 1919 additions and 87 deletions

View File

@@ -0,0 +1,24 @@
namespace CutList.Web.DTOs;
public class CuttingToolDto
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal KerfInches { get; set; }
public bool IsDefault { get; set; }
public bool IsActive { get; set; }
}
public class CreateCuttingToolDto
{
public string Name { get; set; } = string.Empty;
public decimal KerfInches { get; set; }
public bool IsDefault { get; set; }
}
public class UpdateCuttingToolDto
{
public string? Name { get; set; }
public decimal? KerfInches { get; set; }
public bool? IsDefault { get; set; }
}

111
CutList.Web/DTOs/JobDtos.cs Normal file
View File

@@ -0,0 +1,111 @@
namespace CutList.Web.DTOs;
public class JobDto
{
public int Id { get; set; }
public string JobNumber { get; set; } = string.Empty;
public string? Name { get; set; }
public string? Customer { get; set; }
public int? CuttingToolId { get; set; }
public string? CuttingToolName { get; set; }
public string? Notes { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public int PartCount { get; set; }
public int StockCount { get; set; }
}
public class JobDetailDto : JobDto
{
public List<JobPartDto> Parts { get; set; } = new();
public List<JobStockDto> Stock { get; set; } = new();
}
public class CreateJobDto
{
public string? Name { get; set; }
public string? Customer { get; set; }
public int? CuttingToolId { get; set; }
public string? Notes { get; set; }
}
public class UpdateJobDto
{
public string? Name { get; set; }
public string? Customer { get; set; }
public int? CuttingToolId { get; set; }
public string? Notes { get; set; }
}
public class JobPartDto
{
public int Id { get; set; }
public int JobId { get; set; }
public int MaterialId { get; set; }
public string MaterialName { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public decimal LengthInches { get; set; }
public string LengthFormatted { get; set; } = string.Empty;
public int Quantity { get; set; }
public int SortOrder { get; set; }
}
public class CreateJobPartDto
{
public int MaterialId { get; set; }
public string Name { get; set; } = string.Empty;
public string Length { get; set; } = string.Empty;
public int Quantity { get; set; } = 1;
}
public class UpdateJobPartDto
{
public int? MaterialId { get; set; }
public string? Name { get; set; }
public string? Length { get; set; }
public int? Quantity { get; set; }
}
public class JobStockDto
{
public int Id { get; set; }
public int JobId { get; set; }
public int MaterialId { get; set; }
public string MaterialName { get; set; } = string.Empty;
public int? StockItemId { get; set; }
public decimal LengthInches { get; set; }
public string LengthFormatted { get; set; } = string.Empty;
public int Quantity { get; set; }
public bool IsCustomLength { get; set; }
public int Priority { get; set; }
public int SortOrder { get; set; }
}
public class CreateJobStockDto
{
public int MaterialId { get; set; }
public int? StockItemId { get; set; }
public string Length { get; set; } = string.Empty;
public int Quantity { get; set; } = 1;
public bool IsCustomLength { get; set; }
public int Priority { get; set; } = 10;
}
public class UpdateJobStockDto
{
public int? StockItemId { get; set; }
public string? Length { get; set; }
public int? Quantity { get; set; }
public bool? IsCustomLength { get; set; }
public int? Priority { get; set; }
}
public class QuickCreateJobDto
{
public string? Customer { get; set; }
}
public class PackJobRequestDto
{
public decimal? KerfOverride { get; set; }
}

View File

@@ -0,0 +1,53 @@
namespace CutList.Web.DTOs;
public class MaterialDto
{
public int Id { get; set; }
public string Shape { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
public string? Grade { get; set; }
public string Size { get; set; } = string.Empty;
public string? Description { get; set; }
public bool IsActive { get; set; }
public MaterialDimensionsDto? Dimensions { get; set; }
}
public class CreateMaterialDto
{
public string Shape { get; set; } = string.Empty;
public string? Type { get; set; }
public string? Grade { get; set; }
public string? Size { get; set; }
public string? Description { get; set; }
public Dictionary<string, decimal>? Dimensions { get; set; }
}
public class UpdateMaterialDto
{
public string? Type { get; set; }
public string? Grade { get; set; }
public string? Size { get; set; }
public string? Description { get; set; }
public bool? RegenerateSize { get; set; }
public Dictionary<string, decimal>? Dimensions { get; set; }
}
public class BulkCreateResult
{
public int Created { get; set; }
public int Skipped { get; set; }
public List<string> Errors { get; set; } = new();
}
public class MaterialDimensionsDto
{
public string DimensionType { get; set; } = string.Empty;
public Dictionary<string, decimal> Values { get; set; } = new();
}
public class MaterialSearchDto
{
public string Shape { get; set; } = string.Empty;
public decimal TargetValue { get; set; }
public decimal Tolerance { get; set; } = 0.1m;
}

View File

@@ -0,0 +1,66 @@
namespace CutList.Web.DTOs;
public class PackResponseDto
{
public List<MaterialPackResultDto> Materials { get; set; } = new();
public PackingSummaryDto Summary { get; set; } = new();
}
public class MaterialPackResultDto
{
public int MaterialId { get; set; }
public string MaterialName { get; set; } = string.Empty;
public List<PackedBinDto> InStockBins { get; set; } = new();
public List<PackedBinDto> ToBePurchasedBins { get; set; } = new();
public List<PackedItemDto> ItemsNotPlaced { get; set; } = new();
public MaterialPackingSummaryDto Summary { get; set; } = new();
}
public class PackedBinDto
{
public double LengthInches { get; set; }
public string LengthFormatted { get; set; } = string.Empty;
public double UsedInches { get; set; }
public string UsedFormatted { get; set; } = string.Empty;
public double WasteInches { get; set; }
public string WasteFormatted { get; set; } = string.Empty;
public double Efficiency { get; set; }
public List<PackedItemDto> Items { get; set; } = new();
}
public class PackedItemDto
{
public string Name { get; set; } = string.Empty;
public double LengthInches { get; set; }
public string LengthFormatted { get; set; } = string.Empty;
}
public class PackingSummaryDto
{
public int TotalInStockBins { get; set; }
public int TotalToBePurchasedBins { get; set; }
public int TotalPieces { get; set; }
public double TotalMaterialInches { get; set; }
public string TotalMaterialFormatted { get; set; } = string.Empty;
public double TotalUsedInches { get; set; }
public string TotalUsedFormatted { get; set; } = string.Empty;
public double TotalWasteInches { get; set; }
public string TotalWasteFormatted { get; set; } = string.Empty;
public double Efficiency { get; set; }
public int TotalItemsNotPlaced { get; set; }
public List<MaterialPackingSummaryDto> MaterialSummaries { get; set; } = new();
}
public class MaterialPackingSummaryDto
{
public int MaterialId { get; set; }
public string MaterialName { get; set; } = string.Empty;
public int InStockBins { get; set; }
public int ToBePurchasedBins { get; set; }
public int TotalPieces { get; set; }
public double TotalMaterialInches { get; set; }
public double TotalUsedInches { get; set; }
public double TotalWasteInches { get; set; }
public double Efficiency { get; set; }
public int ItemsNotPlaced { get; set; }
}

View File

@@ -0,0 +1,45 @@
namespace CutList.Web.DTOs;
public class StandalonePackRequestDto
{
public List<PartInputDto> Parts { get; set; } = new();
public List<StockBinInputDto> StockBins { get; set; } = new();
public decimal Kerf { get; set; } = 0.125m;
public string Strategy { get; set; } = "advanced";
}
public class PartInputDto
{
public string Name { get; set; } = string.Empty;
public string Length { get; set; } = string.Empty;
public int Quantity { get; set; } = 1;
}
public class StockBinInputDto
{
public string Length { get; set; } = string.Empty;
public int Quantity { get; set; } = -1;
public int Priority { get; set; } = 25;
}
public class ParseLengthRequestDto
{
public string Input { get; set; } = string.Empty;
}
public class ParseLengthResponseDto
{
public double Inches { get; set; }
public string Formatted { get; set; } = string.Empty;
}
public class FormatLengthRequestDto
{
public double Inches { get; set; }
}
public class FormatLengthResponseDto
{
public string Formatted { get; set; } = string.Empty;
public double Inches { get; set; }
}

View File

@@ -0,0 +1,78 @@
namespace CutList.Web.DTOs;
public class StockItemDto
{
public int Id { get; set; }
public int MaterialId { get; set; }
public string MaterialName { get; set; } = string.Empty;
public decimal LengthInches { get; set; }
public string LengthFormatted { get; set; } = string.Empty;
public string? Name { get; set; }
public int QuantityOnHand { get; set; }
public string? Notes { get; set; }
public bool IsActive { get; set; }
}
public class CreateStockItemDto
{
public int MaterialId { get; set; }
public string Length { get; set; } = string.Empty;
public string? Name { get; set; }
public int QuantityOnHand { get; set; }
public string? Notes { get; set; }
}
public class UpdateStockItemDto
{
public string? Length { get; set; }
public string? Name { get; set; }
public string? Notes { get; set; }
}
public class StockTransactionDto
{
public int Id { get; set; }
public int StockItemId { get; set; }
public int Quantity { get; set; }
public string Type { get; set; } = string.Empty;
public int? JobId { get; set; }
public string? JobNumber { get; set; }
public int? SupplierId { get; set; }
public string? SupplierName { get; set; }
public decimal? UnitPrice { get; set; }
public string? Notes { get; set; }
public DateTime CreatedAt { get; set; }
}
public class AddStockDto
{
public int Quantity { get; set; }
public int? SupplierId { get; set; }
public decimal? UnitPrice { get; set; }
public string? Notes { get; set; }
}
public class UseStockDto
{
public int Quantity { get; set; }
public int? JobId { get; set; }
public string? Notes { get; set; }
}
public class AdjustStockDto
{
public int NewQuantity { get; set; }
public string? Notes { get; set; }
}
public class ScrapStockDto
{
public int Quantity { get; set; }
public string? Notes { get; set; }
}
public class StockPricingDto
{
public decimal? AverageCost { get; set; }
public decimal? LastPurchasePrice { get; set; }
}

View File

@@ -0,0 +1,57 @@
namespace CutList.Web.DTOs;
public class SupplierDto
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? ContactInfo { get; set; }
public string? Notes { get; set; }
public bool IsActive { get; set; }
}
public class CreateSupplierDto
{
public string Name { get; set; } = string.Empty;
public string? ContactInfo { get; set; }
public string? Notes { get; set; }
}
public class UpdateSupplierDto
{
public string? Name { get; set; }
public string? ContactInfo { get; set; }
public string? Notes { get; set; }
}
public class OfferingDto
{
public int Id { get; set; }
public int SupplierId { get; set; }
public string? SupplierName { get; set; }
public int StockItemId { get; set; }
public string? MaterialName { get; set; }
public decimal? LengthInches { get; set; }
public string? LengthFormatted { get; set; }
public string? PartNumber { get; set; }
public string? SupplierDescription { get; set; }
public decimal? Price { get; set; }
public string? Notes { get; set; }
public bool IsActive { get; set; }
}
public class CreateOfferingDto
{
public int StockItemId { get; set; }
public string? PartNumber { get; set; }
public string? SupplierDescription { get; set; }
public decimal? Price { get; set; }
public string? Notes { get; set; }
}
public class UpdateOfferingDto
{
public string? PartNumber { get; set; }
public string? SupplierDescription { get; set; }
public decimal? Price { get; set; }
public string? Notes { get; set; }
}