using BlueLaminate.EFCore.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace BlueLaminate.EFCore.Configurations; public class CsMoneyListingConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder entity) { // cs.money's sell-order id is the natural key; ingest upserts against it and // must never create duplicates. entity.HasIndex(e => e.SellOrderId).IsUnique(); entity.Property(e => e.Price).HasPrecision(18, 2); entity.Property(e => e.PriceBeforeDiscount).HasPrecision(18, 2); entity.Property(e => e.ComputedPrice).HasPrecision(18, 2); // Full precision to match SkinInstance for exact fingerprint joins. entity.Property(e => e.FloatValue).HasColumnType("numeric(20,18)"); // Enum as text so the DB is self-describing (matches the project's leaning). entity.Property(e => e.Status).HasConversion(); // Targeted scrape: results are filtered/sorted by skin+wear and by activity. entity.HasIndex(e => new { e.SkinId, e.ConditionId }); entity.HasIndex(e => e.Status); entity.HasIndex(e => e.AssetId); // Each job targets a known skin, so this link is required (Restrict: a skin // with live listings shouldn't be deleted out from under them). entity.HasOne(e => e.Skin) .WithMany() .HasForeignKey(e => e.SkinId) .OnDelete(DeleteBehavior.Restrict); entity.HasOne(e => e.Condition) .WithMany() .HasForeignKey(e => e.ConditionId) .OnDelete(DeleteBehavior.SetNull); // Listings roll up to the physical item they represent (shared with CSFloat). entity.HasOne(e => e.SkinInstance) .WithMany() .HasForeignKey(e => e.SkinInstanceId) .OnDelete(DeleteBehavior.SetNull); } }