using Microsoft.EntityFrameworkCore; using eprintServer.Entities; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using System.Collections.Generic; using System.Linq; using System; using Microsoft.EntityFrameworkCore.ChangeTracking; namespace eprintServer.Data { public class DataContext : DbContext { public DbSet Users { get; set; } public DbSet FileModels { get; set; } public DbSet UserDevices { get; set; } public DbSet BrandingColors { get; set; } public DbSet ContactSettings { get; set; } public DbSet SellableProducts { get; set; } public DbSet ProductCategories { get; set; } public DbSet OAuthSettings { get; set; } public DbSet DynamicValues { get; set; } public DbSet Currencies { get; set; } public DbSet Languages { get; set; } public DbSet TranslationSettings { get; set; } public DbSet Blogs { get; set; } public DbSet Faqs { get; set; } public DbSet Offers { get; set; } public DbSet OfferProducts { get; set; } public DbSet CustomizableProducts { get; set; } public DbSet TextureSlots { get; set; } public DbSet Mockups { get; set; } public DbSet Steps { get; set; } public DbSet FormElements { get; set; } public DbSet FormElementOptions { get; set; } public DbSet StepTemplates { get; set; } public DbSet UserCustomizations { get; set; } public DbSet UserCustomizationSteps { get; set; } public DbSet UserCustomizationFieldValues { get; set; } public DbSet UserCanvasDesigns { get; set; } public DbSet UserMockups { get; set; } public DbSet CarouselItems { get; set; } public DbSet NotificationModels { get; set; } public DbSet Payments { get; set; } public DbSet Orders { get; set; } public DbSet Invoices { get; set; } public DbSet OrderItems { get; set; } public DbSet UserAddresses { get; set; } public DbSet ReportSettings { get; set; } public DbSet RevokedTokens { get; set; } public DataContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // --- VALUE CONVERTERS --- var languageTagConverter = new ValueConverter, string>( v => string.Join(',', v), v => v.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList() ); var listComparer = new ValueComparer>( (c1, c2) => c1.SequenceEqual(c2), c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())), c => c.ToList() ); // --- USER CONFIGURATION --- modelBuilder.Entity(entity => { entity.ToTable("users_table"); entity.Property(u => u.Id).HasColumnName("user_id"); entity.HasIndex(u => u.Username).IsUnique(); entity.HasIndex(u => u.Email).IsUnique(); entity.HasOne(u => u.Image).WithOne().HasForeignKey("users_profile_media").OnDelete(DeleteBehavior.Cascade); entity.HasOne(u => u.Device).WithOne().HasForeignKey("user_device").OnDelete(DeleteBehavior.Cascade); entity.HasMany(u => u.Orders).WithOne(o => o.User).HasForeignKey(o => o.UserId).OnDelete(DeleteBehavior.Cascade); entity.HasMany(u => u.Invoices).WithOne(i => i.User).HasForeignKey(i => i.UserId).OnDelete(DeleteBehavior.Cascade); entity.Property(u => u.Role).HasColumnType("integer"); }); // --- BLOG CONFIGURATION (SOLVES MULTIPLE RELATIONSHIP WARNING) --- modelBuilder.Entity(entity => { entity.ToTable("blog_posts"); entity.HasMany(b => b.TitleDynamic).WithOne().HasForeignKey("BlogTitleId").OnDelete(DeleteBehavior.Cascade); entity.HasMany(b => b.ContentDynamic).WithOne().HasForeignKey("BlogContentId").OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.HasOne(b => b.Logo).WithOne().HasForeignKey(b => b.LogoId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); entity.HasOne(b => b.Favicon).WithOne().HasForeignKey(b => b.FaviconId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.ToTable("translation_settings_table"); entity.Property(t => t.Id).ValueGeneratedNever(); entity.Property(t => t.ActiveLanguageTags).HasConversion(languageTagConverter).Metadata.SetValueComparer(listComparer); entity.Property(t => t.ActiveLanguageTags).HasColumnType("varchar(500)"); }); modelBuilder.Entity(entity => { entity.ToTable("languages"); entity.HasIndex(l => l.Tag).IsUnique(); }); modelBuilder.Entity(entity => { entity.HasOne(pc => pc.Image).WithOne().HasForeignKey(pc => pc.ImageId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); entity.HasMany(pc => pc.Name).WithOne().HasForeignKey("ProductCategoryId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(pc => pc.Products).WithOne(p => p.Category).HasForeignKey(p => p.CategoryId).IsRequired().OnDelete(DeleteBehavior.Restrict); entity.HasMany(pc => pc.CustomizableProducts).WithOne(p => p.Category).HasForeignKey(p => p.CategoryId).IsRequired().OnDelete(DeleteBehavior.Restrict); }); modelBuilder.Entity(entity => { entity.HasMany(f => f.Question).WithOne().HasForeignKey("FaqQuestionId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(f => f.Answer).WithOne().HasForeignKey("FaqAnswerId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.ToTable("revoked_tokens"); entity.HasKey(e => e.Id); entity.Property(e => e.Token).IsRequired().HasMaxLength(500); entity.HasIndex(e => e.Token).IsUnique(); }); modelBuilder.Entity(entity => { entity.HasMany(p => p.Names).WithOne().HasForeignKey("SellableProductNameId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(p => p.Descriptions).WithOne().HasForeignKey("SellableProductDescriptionId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.ToTable("offers_table"); entity.HasOne(o => o.BannerImage).WithOne().HasForeignKey(o => o.BannerImageId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); entity.HasMany(o => o.Products).WithOne(op => op.Offer).HasForeignKey(op => op.OfferForeignKey).OnDelete(DeleteBehavior.Cascade); entity.HasMany(o => o.Title).WithOne().HasForeignKey("OfferTitleId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(o => o.Description).WithOne().HasForeignKey("OfferDescriptionId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.ToTable("offer_products_table"); entity.Ignore(op => op.OfferId); entity.HasOne(op => op.ProductImage).WithOne().HasForeignKey(op => op.ProductImageId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.HasOne(cp => cp.Category).WithMany(pc => pc.CustomizableProducts).HasForeignKey(cp => cp.CategoryId).IsRequired().OnDelete(DeleteBehavior.Restrict); entity.HasMany(cp => cp.Names).WithOne().HasForeignKey("CustomizableProductNameId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(cp => cp.Descriptions).WithOne().HasForeignKey("CustomizableProductDescriptionId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(cp => cp.Steps).WithOne(s => s.Product).HasForeignKey(s => s.ProductId).OnDelete(DeleteBehavior.Cascade); entity.HasOne(cp => cp.Image).WithOne().HasForeignKey(cp => cp.ImageId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); entity.Property(cp => cp.QuantityPricingConfig).HasColumnType("jsonb"); entity.Property(cp => cp.ThreeDConfig).HasColumnType("jsonb"); entity.HasOne(cp => cp.UvMapImage).WithOne().HasForeignKey(cp => cp.UvMapImageId).OnDelete(DeleteBehavior.SetNull); entity.HasOne(cp => cp.ThreeDModelFile).WithOne().HasForeignKey(cp => cp.ThreeDModelFileId).OnDelete(DeleteBehavior.SetNull); entity.HasMany(cp => cp.TextureSlots).WithOne().HasForeignKey(ts => ts.CustomizableProductId).OnDelete(DeleteBehavior.Cascade); entity.HasMany(cp => cp.Mockups).WithOne().HasForeignKey(m => m.CustomizableProductId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.ToTable("texture_slots"); entity.Property(ts => ts.UvCoordinates).HasColumnType("jsonb"); entity.HasOne(ts => ts.File).WithOne().HasForeignKey(ts => ts.FileId).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.ToTable("product_mockups"); entity.HasOne(m => m.File).WithOne().HasForeignKey(m => m.FileId).OnDelete(DeleteBehavior.SetNull); entity.HasOne(m => m.Thumbnail).WithOne().HasForeignKey(m => m.ThumbnailFileId).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.HasOne(s => s.Product).WithMany(cp => cp.Steps).HasForeignKey(s => s.ProductId).OnDelete(DeleteBehavior.Cascade); entity.HasMany(s => s.StepName).WithOne().HasForeignKey("StepNameId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(s => s.FormElements).WithOne(fe => fe.Step).HasForeignKey(fe => fe.StepId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.HasOne(fe => fe.Step).WithMany(s => s.FormElements).HasForeignKey(fe => fe.StepId).OnDelete(DeleteBehavior.Cascade); entity.HasMany(fe => fe.Label).WithOne().HasForeignKey("FormElementLabelId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(fe => fe.Options).WithOne(feo => feo.FormElement).HasForeignKey(feo => feo.FormElementId).OnDelete(DeleteBehavior.Cascade); entity.Property(b => b.ColorPricingConfig).HasColumnType("jsonb"); entity.Property(b => b.QuantityPricingConfig).HasColumnType("jsonb"); }); modelBuilder.Entity(entity => { entity.HasOne(feo => feo.FormElement).WithMany(fe => fe.Options).HasForeignKey(feo => feo.FormElementId).OnDelete(DeleteBehavior.Cascade); entity.HasMany(feo => feo.OptionLabel).WithOne().HasForeignKey("FormElementOptionLabelId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.Property(b => b.PriceConfig).HasColumnType("jsonb"); }); modelBuilder.Entity(entity => { entity.HasMany(st => st.TemplateName).WithOne().HasForeignKey("StepTemplateNameId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(st => st.FormElements).WithOne().HasForeignKey("StepTemplateId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.HasOne(uc => uc.Product).WithMany().HasForeignKey(uc => uc.ProductId).OnDelete(DeleteBehavior.Restrict); entity.HasMany(uc => uc.Steps).WithOne(ucs => ucs.UserCustomization).HasForeignKey(ucs => ucs.UserCustomizationId).OnDelete(DeleteBehavior.Cascade); entity.HasIndex(uc => uc.UserId); entity.HasIndex(uc => uc.ProgressId).IsUnique(); entity.HasMany(uc => uc.OrderItems).WithOne(oi => oi.UserCustomization).HasForeignKey(oi => oi.UserCustomizationId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.HasOne(ucs => ucs.UserCustomization).WithMany(uc => uc.Steps).HasForeignKey(ucs => ucs.UserCustomizationId).OnDelete(DeleteBehavior.Cascade); entity.HasMany(ucs => ucs.FieldValues).WithOne(ucfv => ucfv.UserCustomizationStep).HasForeignKey(ucfv => ucfv.UserCustomizationStepId).OnDelete(DeleteBehavior.Cascade); entity.HasOne(ucs => ucs.UserMockup).WithOne(um => um.UserCustomizationStep).HasForeignKey(um => um.UserCustomizationStepId).IsRequired(false).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.HasOne(ucfv => ucfv.UserCustomizationStep).WithMany(ucs => ucs.FieldValues).HasForeignKey(ucfv => ucfv.UserCustomizationStepId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.ToTable("user_mockups"); entity.Property(um => um.Id).HasColumnName("id").ValueGeneratedOnAdd(); entity.HasOne(um => um.File).WithOne().HasForeignKey(um => um.FileId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); entity.HasOne(um => um.Thumbnail).WithOne().HasForeignKey(um => um.ThumbnailFileId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.HasOne(ucd => ucd.UserCustomizationStep).WithOne().HasForeignKey(ucd => ucd.UserCustomizationStepId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.ToTable("carousel_items"); entity.HasMany(c => c.Title).WithOne().HasForeignKey("CarouselTitleId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(c => c.Description).WithOne().HasForeignKey("CarouselDescriptionId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasMany(c => c.ButtonText).WithOne().HasForeignKey("CarouselButtonTextId").IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasOne(c => c.Image).WithOne().HasForeignKey(c => c.ImageId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.ToTable("user_addresses"); entity.Property(ua => ua.Id).HasColumnName("id"); }); modelBuilder.Entity(entity => { entity.ToTable("Order"); entity.Property(o => o.Id).HasColumnName("id"); entity.HasMany(o => o.OrderItems).WithOne(oi => oi.Order).HasForeignKey(oi => oi.OrderId); entity.HasOne(o => o.UserAddress).WithMany().HasForeignKey(o => o.AddressId).OnDelete(DeleteBehavior.SetNull); entity.Property(o => o.Status).HasColumnType("integer"); }); modelBuilder.Entity(entity => { entity.ToTable("Payments"); entity.Property(p => p.OrderId).HasColumnName("order_id"); entity.Property(p => p.Id).HasColumnName("id"); entity.HasOne(p => p.Order).WithMany(o => o.Payments).HasForeignKey(p => p.OrderId).HasConstraintName("fk_order"); }); modelBuilder.Entity(entity => { entity.ToTable("invoices"); entity.Property(i => i.Id).HasColumnName("id"); entity.HasOne(i => i.Order).WithMany().HasForeignKey(i => i.OrderId).OnDelete(DeleteBehavior.Restrict); entity.HasMany(i => i.InvoiceItems).WithOne(oi => oi.Invoice).HasForeignKey(oi => oi.InvoiceId).OnDelete(DeleteBehavior.Cascade); entity.Property(i => i.Status).HasColumnType("integer"); }); modelBuilder.Entity(entity => { entity.Property(e => e.AdminEmailList).HasColumnType("text[]").Metadata.SetValueComparer(listComparer); }); modelBuilder.Entity(entity => { entity.ToTable("OrderItem"); entity.Property(oi => oi.Id).HasColumnName("id"); entity.HasOne(oi => oi.Order).WithMany(o => o.OrderItems).HasForeignKey(oi => oi.OrderId).IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasOne(oi => oi.Invoice).WithMany(i => i.InvoiceItems).HasForeignKey(oi => oi.InvoiceId).IsRequired(false).OnDelete(DeleteBehavior.Cascade); entity.HasOne(oi => oi.SellableProduct).WithMany().HasForeignKey(oi => oi.SellableProductId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); entity.HasOne(oi => oi.CustomizableProduct).WithMany().HasForeignKey(oi => oi.CustomizableProductId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); entity.HasOne(oi => oi.UserCustomization).WithMany(uc => uc.OrderItems).HasForeignKey(oi => oi.UserCustomizationId).IsRequired(false).OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.Property(dv => dv.Value).HasColumnType("text"); entity.Property(dv => dv.LanguageTag).HasColumnType("varchar(10)"); // MATCHING DATABASE COLUMN NAMES entity.Property("ProductCategoryId").HasColumnName("ProductCategoryId"); entity.Property("FaqQuestionId").HasColumnName("FaqQuestionId"); entity.Property("FaqAnswerId").HasColumnName("FaqAnswerId"); entity.Property("OfferTitleId").HasColumnName("OfferTitleId"); entity.Property("OfferDescriptionId").HasColumnName("OfferDescriptionId"); entity.Property("CustomizableProductNameId").HasColumnName("CustomizableProductNameId"); entity.Property("CustomizableProductDescriptionId").HasColumnName("CustomizableProductDescriptionId"); entity.Property("StepNameId").HasColumnName("StepNameId"); entity.Property("FormElementLabelId").HasColumnName("FormElementLabelId"); entity.Property("FormElementOptionLabelId").HasColumnName("FormElementOptionLabelId"); entity.Property("StepTemplateNameId").HasColumnName("StepTemplateNameId"); entity.Property("CarouselTitleId").HasColumnName("CarouselTitleId"); entity.Property("CarouselDescriptionId").HasColumnName("CarouselDescriptionId"); entity.Property("CarouselButtonTextId").HasColumnName("CarouselButtonTextId"); entity.Property("SellableProductNameId").HasColumnName("SellableProductNameId"); entity.Property("SellableProductDescriptionId").HasColumnName("SellableProductDescriptionId"); // ADDED BLOG FOREIGN KEYS entity.Property("BlogTitleId").HasColumnName("BlogTitleId"); entity.Property("BlogContentId").HasColumnName("BlogContentId"); entity.HasIndex("ProductCategoryId"); entity.HasIndex("FaqQuestionId"); entity.HasIndex("FaqAnswerId"); entity.HasIndex("OfferTitleId"); entity.HasIndex("OfferDescriptionId"); entity.HasIndex("CustomizableProductNameId"); entity.HasIndex("CustomizableProductDescriptionId"); entity.HasIndex("StepNameId"); entity.HasIndex("FormElementLabelId"); entity.HasIndex("FormElementOptionLabelId"); entity.HasIndex("StepTemplateNameId"); entity.HasIndex("CarouselTitleId"); entity.HasIndex("CarouselDescriptionId"); entity.HasIndex("CarouselButtonTextId"); entity.HasIndex("SellableProductNameId"); entity.HasIndex("SellableProductDescriptionId"); entity.HasIndex("BlogTitleId"); entity.HasIndex("BlogContentId"); }); } } }