Add storage_location and is_archived fields to Spool entity to complete the filament inventory entity definition per CUB-28 requirements. Changes: - Spool entity: add IsArchived (bool, default false) and StorageLocation (nullable string, max 200) for physical inventory tracking - SpoolConfiguration: add snake_case column mappings, defaults, and indexes (ix_spools_is_archived, ix_spools_active_archived composite) - FilamentDtos: add IsArchived + StorageLocation to Response, Create, Update - FilamentQueryDtos: add IncludeArchived and StorageLocation query filters - FilamentsController: wire new fields into query, create, update, mapping - FilamentValidators: add StorageLocation max-length validation Build: PASS (0 errors)
138 lines
4.7 KiB
C#
138 lines
4.7 KiB
C#
using Extrudex.Domain.Entities;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
|
|
|
namespace Extrudex.Infrastructure.Data.Configurations;
|
|
|
|
public class SpoolConfiguration : BaseEntityConfiguration<Spool>
|
|
{
|
|
public override void Configure(EntityTypeBuilder<Spool> builder)
|
|
{
|
|
base.Configure(builder);
|
|
|
|
builder.Property(e => e.MaterialBaseId)
|
|
.HasColumnName("material_base_id")
|
|
.IsRequired();
|
|
|
|
builder.Property(e => e.MaterialFinishId)
|
|
.HasColumnName("material_finish_id")
|
|
.IsRequired();
|
|
|
|
builder.Property(e => e.MaterialModifierId)
|
|
.HasColumnName("material_modifier_id");
|
|
|
|
builder.Property(e => e.Brand)
|
|
.HasColumnName("brand")
|
|
.IsRequired()
|
|
.HasMaxLength(200);
|
|
|
|
builder.Property(e => e.ColorName)
|
|
.HasColumnName("color_name")
|
|
.IsRequired()
|
|
.HasMaxLength(200);
|
|
|
|
builder.Property(e => e.ColorHex)
|
|
.HasColumnName("color_hex")
|
|
.IsRequired()
|
|
.HasMaxLength(7); // "#RRGGBB" format
|
|
|
|
builder.Property(e => e.WeightTotalGrams)
|
|
.HasColumnName("weight_total_grams")
|
|
.HasPrecision(10, 2)
|
|
.IsRequired();
|
|
|
|
builder.Property(e => e.WeightRemainingGrams)
|
|
.HasColumnName("weight_remaining_grams")
|
|
.HasPrecision(10, 2)
|
|
.IsRequired();
|
|
|
|
builder.Property(e => e.FilamentDiameterMm)
|
|
.HasColumnName("filament_diameter_mm")
|
|
.HasPrecision(6, 3)
|
|
.IsRequired();
|
|
|
|
builder.Property(e => e.SpoolSerial)
|
|
.HasColumnName("spool_serial")
|
|
.IsRequired()
|
|
.HasMaxLength(200);
|
|
|
|
builder.Property(e => e.PurchasePrice)
|
|
.HasColumnName("purchase_price")
|
|
.HasPrecision(10, 2);
|
|
|
|
builder.Property(e => e.PurchaseDate)
|
|
.HasColumnName("purchase_date");
|
|
|
|
builder.Property(e => e.IsActive)
|
|
.HasColumnName("is_active")
|
|
.HasDefaultValue(true)
|
|
.IsRequired();
|
|
|
|
builder.Property(e => e.IsArchived)
|
|
.HasColumnName("is_archived")
|
|
.HasDefaultValue(false)
|
|
.IsRequired();
|
|
|
|
builder.Property(e => e.StorageLocation)
|
|
.HasColumnName("storage_location")
|
|
.HasMaxLength(200);
|
|
|
|
// Unique index on spool_serial — critical for barcode/QR scanning
|
|
builder.HasIndex(e => e.SpoolSerial)
|
|
.IsUnique()
|
|
.HasDatabaseName("ix_spools_spool_serial");
|
|
|
|
// Index on material_base_id for spool filtering
|
|
builder.HasIndex(e => e.MaterialBaseId)
|
|
.HasDatabaseName("ix_spools_material_base_id");
|
|
|
|
// Index on material_finish_id for spool filtering
|
|
builder.HasIndex(e => e.MaterialFinishId)
|
|
.HasDatabaseName("ix_spools_material_finish_id");
|
|
|
|
// Index on material_modifier_id for spool filtering
|
|
builder.HasIndex(e => e.MaterialModifierId)
|
|
.HasDatabaseName("ix_spools_material_modifier_id");
|
|
|
|
// Index on is_active for active spool queries
|
|
builder.HasIndex(e => e.IsActive)
|
|
.HasDatabaseName("ix_spools_is_active");
|
|
|
|
// Index on is_archived for inventory filtering (exclude archived from default views)
|
|
builder.HasIndex(e => e.IsArchived)
|
|
.HasDatabaseName("ix_spools_is_archived");
|
|
|
|
// Composite index on is_active + is_archived for common inventory queries
|
|
builder.HasIndex(e => new { e.IsActive, e.IsArchived })
|
|
.HasDatabaseName("ix_spools_active_archived");
|
|
|
|
// Relationships
|
|
builder.HasOne(e => e.MaterialBase)
|
|
.WithMany(e => e.Spools)
|
|
.HasForeignKey(e => e.MaterialBaseId)
|
|
.HasConstraintName("fk_spools_material_base")
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
|
|
builder.HasOne(e => e.MaterialFinish)
|
|
.WithMany(e => e.Spools)
|
|
.HasForeignKey(e => e.MaterialFinishId)
|
|
.HasConstraintName("fk_spools_material_finish")
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
|
|
builder.HasOne(e => e.MaterialModifier)
|
|
.WithMany(e => e.Spools)
|
|
.HasForeignKey(e => e.MaterialModifierId)
|
|
.HasConstraintName("fk_spools_material_modifier")
|
|
.OnDelete(DeleteBehavior.SetNull);
|
|
|
|
builder.HasMany(e => e.AmsSlots)
|
|
.WithOne(e => e.Spool!)
|
|
.HasForeignKey(e => e.SpoolId)
|
|
.HasConstraintName("fk_ams_slots_spool");
|
|
|
|
builder.HasMany(e => e.PrintJobs)
|
|
.WithOne(e => e.Spool)
|
|
.HasForeignKey(e => e.SpoolId)
|
|
.HasConstraintName("fk_print_jobs_spool");
|
|
}
|
|
} |