Files
Extrudex/backend/API/DTOs/Filaments/FilamentDtos.cs
cubecraft-agents[bot] 230c3b295d initial commit
2026-04-25 18:51:05 +00:00

199 lines
9.5 KiB
C#

using System.ComponentModel.DataAnnotations;
namespace Extrudex.API.DTOs.Filaments;
/// <summary>
/// Response DTO for a filament spool — the core inventory unit of Extrudex.
/// Contains all spool details including denormalized material names for display.
/// </summary>
public class FilamentResponse
{
/// <summary>Unique identifier for the filament spool.</summary>
public Guid Id { get; set; }
/// <summary>Foreign key to the base material.</summary>
public Guid MaterialBaseId { get; set; }
/// <summary>Name of the base material (e.g., "PLA", "PETG").</summary>
public string MaterialBaseName { get; set; } = string.Empty;
/// <summary>Foreign key to the material finish.</summary>
public Guid MaterialFinishId { get; set; }
/// <summary>Name of the material finish (e.g., "Basic", "Matte").</summary>
public string MaterialFinishName { get; set; } = string.Empty;
/// <summary>Foreign key to the optional material modifier. Null if none.</summary>
public Guid? MaterialModifierId { get; set; }
/// <summary>Name of the material modifier (e.g., "Carbon Fiber"). Null if none.</summary>
public string? MaterialModifierName { get; set; }
/// <summary>Brand name (e.g., "Bambu Lab", "Polymaker").</summary>
public string Brand { get; set; } = string.Empty;
/// <summary>Human-readable color name (e.g., "Fire Engine Red").</summary>
public string ColorName { get; set; } = string.Empty;
/// <summary>Hex color code (e.g., "#FF0000").</summary>
public string ColorHex { get; set; } = string.Empty;
/// <summary>Total spool weight in grams when full.</summary>
public decimal WeightTotalGrams { get; set; }
/// <summary>Current remaining weight in grams.</summary>
public decimal WeightRemainingGrams { get; set; }
/// <summary>Filament diameter in millimeters. Typically 1.75mm.</summary>
public decimal FilamentDiameterMm { get; set; }
/// <summary>Manufacturer-assigned serial number. Must be unique.</summary>
public string SpoolSerial { get; set; } = string.Empty;
/// <summary>Purchase price per spool. Null if not tracked.</summary>
public decimal? PurchasePrice { get; set; }
/// <summary>Date the spool was purchased or received.</summary>
public DateTime? PurchaseDate { get; set; }
/// <summary>Whether the spool is currently active and available.</summary>
public bool IsActive { get; set; }
/// <summary>Timestamp when this record was created (UTC).</summary>
public DateTime CreatedAt { get; set; }
/// <summary>Timestamp when this record was last updated (UTC).</summary>
public DateTime UpdatedAt { get; set; }
/// <summary>
/// URL to the QR code image for this spool.
/// Encodes a deep link to the spool's detail page.
/// </summary>
public string QrCodeUrl { get; set; } = string.Empty;
}
/// <summary>
/// Request DTO for creating a new filament spool.
/// All required fields must be provided. MaterialFinish is required — use "Basic" as the default.
/// </summary>
public class CreateFilamentRequest
{
/// <summary>Foreign key to the base material. Required.</summary>
[Required(ErrorMessage = "MaterialBaseId is required.")]
public Guid MaterialBaseId { get; set; }
/// <summary>Foreign key to the material finish. Required — default is "Basic".</summary>
[Required(ErrorMessage = "MaterialFinishId is required.")]
public Guid MaterialFinishId { get; set; }
/// <summary>Foreign key to the optional material modifier. Null if none applies.</summary>
public Guid? MaterialModifierId { get; set; }
/// <summary>Brand name (e.g., "Bambu Lab", "Polymaker"). Required, max 200 characters.</summary>
[Required(ErrorMessage = "Brand is required.")]
[StringLength(200, MinimumLength = 1, ErrorMessage = "Brand must be between 1 and 200 characters.")]
public string Brand { get; set; } = string.Empty;
/// <summary>Human-readable color name (e.g., "Fire Engine Red"). Required, max 200 characters.</summary>
[Required(ErrorMessage = "ColorName is required.")]
[StringLength(200, MinimumLength = 1, ErrorMessage = "ColorName must be between 1 and 200 characters.")]
public string ColorName { get; set; } = string.Empty;
/// <summary>Hex color code (e.g., "#FF0000"). Required, must be valid 7-char hex.</summary>
[Required(ErrorMessage = "ColorHex is required.")]
[RegularExpression(@"^#[0-9A-Fa-f]{6}$", ErrorMessage = "ColorHex must be a valid hex color code (e.g., #FF0000).")]
[StringLength(7, MinimumLength = 7, ErrorMessage = "ColorHex must be exactly 7 characters (e.g., #FF0000).")]
public string ColorHex { get; set; } = string.Empty;
/// <summary>Total spool weight in grams when full. Must be greater than zero.</summary>
[Required(ErrorMessage = "WeightTotalGrams is required.")]
[Range(0.01, 100000, ErrorMessage = "Total weight must be between 0.01 and 100,000 grams.")]
public decimal WeightTotalGrams { get; set; }
/// <summary>Current remaining weight in grams. Must be non-negative.</summary>
[Required(ErrorMessage = "WeightRemainingGrams is required.")]
[Range(0, 100000, ErrorMessage = "Remaining weight must be between 0 and 100,000 grams.")]
public decimal WeightRemainingGrams { get; set; }
/// <summary>Filament diameter in mm. Defaults to 1.75. Must be greater than zero.</summary>
[Range(0.1, 10.0, ErrorMessage = "Filament diameter must be between 0.1 and 10.0 mm.")]
public decimal FilamentDiameterMm { get; set; } = 1.75m;
/// <summary>Manufacturer-assigned serial number. Must be unique, max 200 characters.</summary>
[Required(ErrorMessage = "SpoolSerial is required.")]
[StringLength(200, MinimumLength = 1, ErrorMessage = "SpoolSerial must be between 1 and 200 characters.")]
public string SpoolSerial { get; set; } = string.Empty;
/// <summary>Optional purchase price per spool. Must be non-negative if provided.</summary>
[Range(0, 1000000, ErrorMessage = "Purchase price must be between 0 and 1,000,000.")]
public decimal? PurchasePrice { get; set; }
/// <summary>Optional purchase date. Must be a valid date if provided.</summary>
public DateTime? PurchaseDate { get; set; }
/// <summary>Whether the spool is active. Defaults to true.</summary>
public bool IsActive { get; set; } = true;
}
/// <summary>
/// Request DTO for updating an existing filament spool.
/// All required fields must be provided for a full update.
/// </summary>
public class UpdateFilamentRequest
{
/// <summary>Foreign key to the base material. Required.</summary>
[Required(ErrorMessage = "MaterialBaseId is required.")]
public Guid MaterialBaseId { get; set; }
/// <summary>Foreign key to the material finish. Required.</summary>
[Required(ErrorMessage = "MaterialFinishId is required.")]
public Guid MaterialFinishId { get; set; }
/// <summary>Foreign key to the optional material modifier. Null if none applies.</summary>
public Guid? MaterialModifierId { get; set; }
/// <summary>Brand name. Required, max 200 characters.</summary>
[Required(ErrorMessage = "Brand is required.")]
[StringLength(200, MinimumLength = 1, ErrorMessage = "Brand must be between 1 and 200 characters.")]
public string Brand { get; set; } = string.Empty;
/// <summary>Human-readable color name. Required, max 200 characters.</summary>
[Required(ErrorMessage = "ColorName is required.")]
[StringLength(200, MinimumLength = 1, ErrorMessage = "ColorName must be between 1 and 200 characters.")]
public string ColorName { get; set; } = string.Empty;
/// <summary>Hex color code (e.g., "#FF0000"). Required, must be valid 7-char hex.</summary>
[Required(ErrorMessage = "ColorHex is required.")]
[RegularExpression(@"^#[0-9A-Fa-f]{6}$", ErrorMessage = "ColorHex must be a valid hex color code (e.g., #FF0000).")]
[StringLength(7, MinimumLength = 7, ErrorMessage = "ColorHex must be exactly 7 characters (e.g., #FF0000).")]
public string ColorHex { get; set; } = string.Empty;
/// <summary>Total spool weight in grams when full. Must be greater than zero.</summary>
[Required(ErrorMessage = "WeightTotalGrams is required.")]
[Range(0.01, 100000, ErrorMessage = "Total weight must be between 0.01 and 100,000 grams.")]
public decimal WeightTotalGrams { get; set; }
/// <summary>Current remaining weight in grams. Must be non-negative.</summary>
[Required(ErrorMessage = "WeightRemainingGrams is required.")]
[Range(0, 100000, ErrorMessage = "Remaining weight must be between 0 and 100,000 grams.")]
public decimal WeightRemainingGrams { get; set; }
/// <summary>Filament diameter in mm. Must be greater than zero.</summary>
[Range(0.1, 10.0, ErrorMessage = "Filament diameter must be between 0.1 and 10.0 mm.")]
public decimal FilamentDiameterMm { get; set; } = 1.75m;
/// <summary>Manufacturer-assigned serial number. Must be unique, max 200 characters.</summary>
[Required(ErrorMessage = "SpoolSerial is required.")]
[StringLength(200, MinimumLength = 1, ErrorMessage = "SpoolSerial must be between 1 and 200 characters.")]
public string SpoolSerial { get; set; } = string.Empty;
/// <summary>Optional purchase price per spool. Must be non-negative if provided.</summary>
[Range(0, 1000000, ErrorMessage = "Purchase price must be between 0 and 1,000,000.")]
public decimal? PurchasePrice { get; set; }
/// <summary>Optional purchase date.</summary>
public DateTime? PurchaseDate { get; set; }
/// <summary>Whether the spool is active.</summary>
public bool IsActive { get; set; } = true;
}