using MealPlan.Api.Models; using Microsoft.EntityFrameworkCore; namespace MealPlan.Api.Data; /// /// Database-first context for the existing PostgreSQL database. /// Tables are mapped explicitly; this context never creates or alters schema. /// public class AppDbContext : DbContext { public AppDbContext(DbContextOptions options) : base(options) { } public DbSet Recipes => Set(); public DbSet Ingredients => Set(); public DbSet RecipeSteps => Set(); public DbSet Users => Set(); public DbSet UserDailyGoals => Set(); public DbSet DrinkCatalog => Set(); public DbSet MealConsumptions => Set(); public DbSet DrinkConsumptions => Set(); public DbSet DietReminders => Set(); public DbSet IngredientCategories => Set(); public DbSet IngredientNutritionCatalog => Set(); public DbSet RefreshTokens => Set(); public DbSet MealPlanEntries => Set(); public DbSet UserFavoriteRecipes => Set(); public DbSet UserFavoriteCatalogItems => Set(); public DbSet DietUserProfiles => Set(); public DbSet DietGeneratorSessions => Set(); public DbSet DietGeneratorDraftMeals => Set(); public DbSet DietGeneratorDraftMealIngredients => Set(); public DbSet RecipeGeneratorSessions => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.HasDefaultSchema("diet"); modelBuilder.Entity(e => { e.HasKey(r => r.Id); e.Property(r => r.Id).UseIdentityByDefaultColumn(); e.Property(r => r.Protein).HasColumnType("numeric(6,2)"); e.Property(r => r.Fat).HasColumnType("numeric(6,2)"); e.Property(r => r.Carbs).HasColumnType("numeric(6,2)"); e.HasMany(r => r.Ingredients) .WithOne(i => i.Recipe!) .HasForeignKey(i => i.RecipeId) .OnDelete(DeleteBehavior.Cascade); e.HasMany(r => r.Steps) .WithOne(s => s.Recipe!) .HasForeignKey(s => s.RecipeId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(i => i.Id); e.Property(i => i.Id).UseIdentityByDefaultColumn(); e.Property(i => i.AmountGrams).HasColumnType("numeric(8,2)"); e.HasOne(i => i.CatalogItem) .WithMany() .HasForeignKey(i => i.CatalogItemId) .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(e => { e.HasKey(s => s.Id); e.Property(s => s.Id).UseIdentityByDefaultColumn(); }); modelBuilder.Entity(e => { e.HasKey(u => u.Id); e.Property(u => u.Id).HasColumnType("uuid"); }); modelBuilder.Entity(e => { e.HasKey(g => g.UserId); e.Property(g => g.UserId).HasColumnType("uuid"); e.Property(g => g.ProteinGoalG).HasColumnType("numeric(6,2)"); e.Property(g => g.FatGoalG).HasColumnType("numeric(6,2)"); e.Property(g => g.CarbsGoalG).HasColumnType("numeric(6,2)"); e.HasOne(g => g.User) .WithMany() .HasForeignKey(g => g.UserId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(d => d.Id); e.Property(d => d.Id).UseIdentityByDefaultColumn(); e.Property(d => d.CaloriesPer100Ml).HasColumnType("numeric(6,2)"); }); modelBuilder.Entity(e => { e.HasKey(m => m.Id); e.Property(m => m.Id).UseIdentityByDefaultColumn(); e.Property(m => m.UserId).HasColumnType("uuid"); e.Property(m => m.Portions).HasColumnType("numeric(4,2)"); e.Property(m => m.ProteinG).HasColumnType("numeric(6,2)"); e.Property(m => m.FatG).HasColumnType("numeric(6,2)"); e.Property(m => m.CarbsG).HasColumnType("numeric(6,2)"); e.HasOne(m => m.User) .WithMany() .HasForeignKey(m => m.UserId) .OnDelete(DeleteBehavior.Cascade); e.HasOne(m => m.Recipe) .WithMany() .HasForeignKey(m => m.RecipeId) .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(e => { e.HasKey(d => d.Id); e.Property(d => d.Id).UseIdentityByDefaultColumn(); e.Property(d => d.UserId).HasColumnType("uuid"); e.HasOne(d => d.User) .WithMany() .HasForeignKey(d => d.UserId) .OnDelete(DeleteBehavior.Cascade); e.HasOne(d => d.DrinkCatalog) .WithMany() .HasForeignKey(d => d.DrinkCatalogId) .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(e => { e.HasKey(r => r.Id); e.Property(r => r.Id).UseIdentityByDefaultColumn(); e.Property(r => r.UserId).HasColumnType("uuid"); e.HasOne(r => r.User) .WithMany() .HasForeignKey(r => r.UserId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(c => c.Id); e.Property(c => c.Id).UseIdentityByDefaultColumn(); }); modelBuilder.Entity(e => { e.HasKey(i => i.Id); e.Property(i => i.Id).UseIdentityByDefaultColumn(); e.Property(i => i.ProteinGPer100G).HasColumnType("numeric(6,2)"); e.Property(i => i.FatGPer100G).HasColumnType("numeric(6,2)"); e.Property(i => i.CarbsGPer100G).HasColumnType("numeric(6,2)"); e.Property(i => i.FiberGPer100G).HasColumnType("numeric(6,2)"); e.HasOne(i => i.Category) .WithMany(c => c.Items) .HasForeignKey(i => i.CategoryId) .OnDelete(DeleteBehavior.Restrict); }); modelBuilder.Entity(e => { e.HasKey(t => t.Token); e.Property(t => t.UserId).HasColumnType("uuid"); e.HasOne(t => t.User) .WithMany() .HasForeignKey(t => t.UserId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(m => m.Id); e.Property(m => m.Id).UseIdentityByDefaultColumn(); e.Property(m => m.UserId).HasColumnType("uuid"); e.Property(m => m.Portions).HasColumnType("numeric(4,2)"); e.HasOne(m => m.User).WithMany().HasForeignKey(m => m.UserId).OnDelete(DeleteBehavior.Cascade); e.HasOne(m => m.Recipe).WithMany().HasForeignKey(m => m.RecipeId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(f => new { f.UserId, f.RecipeId }); e.Property(f => f.UserId).HasColumnType("uuid"); e.HasOne(f => f.Recipe).WithMany().HasForeignKey(f => f.RecipeId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(f => new { f.UserId, f.CatalogItemId }); e.Property(f => f.UserId).HasColumnType("uuid"); e.HasOne(f => f.CatalogItem).WithMany().HasForeignKey(f => f.CatalogItemId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(p => p.UserId); e.Property(p => p.UserId).HasColumnType("uuid"); e.Property(p => p.HeightCm).HasColumnType("numeric(5,2)"); e.Property(p => p.WeightKg).HasColumnType("numeric(5,2)"); e.HasOne(p => p.User) .WithMany() .HasForeignKey(p => p.UserId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(s => s.Id); e.Property(s => s.Id).UseIdentityByDefaultColumn(); e.Property(s => s.UserId).HasColumnType("uuid"); e.Property(s => s.ProposedProteinG).HasColumnType("numeric(6,2)"); e.Property(s => s.ProposedFatG).HasColumnType("numeric(6,2)"); e.Property(s => s.ProposedCarbsG).HasColumnType("numeric(6,2)"); e.Property(s => s.PreferencesJson).HasColumnType("jsonb"); e.HasMany(s => s.DraftMeals).WithOne(m => m.Session!).HasForeignKey(m => m.SessionId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(m => m.Id); e.Property(m => m.Id).UseIdentityByDefaultColumn(); e.Property(m => m.Portions).HasColumnType("numeric(4,2)"); e.Property(m => m.ProteinG).HasColumnType("numeric(6,2)"); e.Property(m => m.FatG).HasColumnType("numeric(6,2)"); e.Property(m => m.CarbsG).HasColumnType("numeric(6,2)"); e.HasOne(m => m.Recipe).WithMany().HasForeignKey(m => m.RecipeId).OnDelete(DeleteBehavior.Cascade); e.HasMany(m => m.PlannedIngredients).WithOne(i => i.DraftMeal!).HasForeignKey(i => i.DraftMealId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(e => { e.HasKey(i => i.Id); e.Property(i => i.Id).UseIdentityByDefaultColumn(); e.Property(i => i.AmountGrams).HasColumnType("numeric(8,2)"); e.HasOne(i => i.SourceIngredient).WithMany().HasForeignKey(i => i.SourceIngredientId) .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(e => { e.HasKey(s => s.Id); e.Property(s => s.Id).UseIdentityByDefaultColumn(); e.Property(s => s.UserId).HasColumnType("uuid"); e.Property(s => s.ConstraintsJson).HasColumnType("jsonb"); e.Property(s => s.DraftJson).HasColumnType("jsonb"); e.HasOne(s => s.SavedRecipe).WithMany().HasForeignKey(s => s.SavedRecipeId).OnDelete(DeleteBehavior.SetNull); }); } }