using BlueLaminate.EFCore.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace BlueLaminate.EFCore.Configurations; public class ListingConfiguration : IEntityTypeConfiguration{ public void Configure(EntityTypeBuilder entity) { // CSFloat's listing id is the natural key; the incremental sweep upserts // against it and must never create duplicates. entity.HasIndex(e => e.CsFloatListingId).IsUnique(); entity.Property(e => e.Price).HasPrecision(18, 2); // Full precision to match SkinInstance for exact fingerprint joins. entity.Property(e => e.FloatValue).HasColumnType("numeric(20,18)"); // Store the enum as text so the DB is self-describing (matches the // project's readable-data leaning over opaque ints). entity.Property(e => e.Status).HasConversion(); // The sweep filters/sorts by item identity and by what's still active. entity.HasIndex(e => new { e.DefIndex, e.PaintIndex }); entity.HasIndex(e => e.Status); // Best-effort catalogue link: a global sweep sees items we may not have, // so the FK is optional and set null if the skin is later removed. entity.HasOne(e => e.Skin) .WithMany() .HasForeignKey(e => e.SkinId) .OnDelete(DeleteBehavior.SetNull); // Wear band the sweep targeted (set directly from the sweep unit, not // best-effort). Set null on delete so a condition row can change without // blocking its listings — matching the cs.money/skin.land tables. entity.HasOne(e => e.Condition) .WithMany() .HasForeignKey(e => e.ConditionId) .OnDelete(DeleteBehavior.SetNull); // Listings roll up to the physical item they represent. entity.HasOne(e => e.SkinInstance) .WithMany(i => i.Listings) .HasForeignKey(e => e.SkinInstanceId) .OnDelete(DeleteBehavior.SetNull); // Dupe analysis groups a fingerprint's listings by asset id. entity.HasIndex(e => e.AssetId); } }