using Extrudex.Domain.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace Extrudex.Infrastructure.Data.Configurations; public class SpoolConfiguration : BaseEntityConfiguration { public override void Configure(EntityTypeBuilder 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"); } }