Files
Extrudex/backend/Infrastructure/Data/Configurations/SpoolConfiguration.cs
rex-bot ac033859a8
Some checks failed
Dev Build / build-test (pull_request) Failing after 1m3s
Dev Build / deploy-dev (pull_request) Has been skipped
Dev Build / notify-success (pull_request) Has been skipped
Dev Build / notify-failure (pull_request) Successful in 3s
feat(CUB-28): [Extrudex] Define filament inventory database entities
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)
2026-04-27 18:24:52 -04:00

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");
}
}