using FinlyticBackend.Entities; using FinlyticCore.Database; using FinlyticCore.Entities.Settings; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; namespace FinlyticBackend.Database; /// /// FinlyticBackend previously implemented no at all, unlike every other /// service - which is why it never had dynamic settings (logging channels etc.) to show in the admin UI. /// public class BackendDbContext : DbContext, ISettingsDbContext { public BackendDbContext(DbContextOptions options) : base(options) { } public DbSet Users => Set(); public DbSet UserDeviceTokens => Set(); public DbSet UserFavoriteAssets => Set(); public DbSet ServiceConfigurations => Set(); public DbSet DynamicSettings => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.HasIndex(e => e.Key).IsUnique(); }); modelBuilder.Entity(entity => { entity.ToTable("users"); entity.Property(u => u.Id).HasColumnName("id"); entity.Property(u => u.Email).HasColumnName("email"); entity.Property(u => u.PasswordHash).HasColumnName("password_hash"); entity.Property(u => u.FullName).HasColumnName("full_name"); entity.Property(u => u.Role).HasColumnName("role"); entity.Property(u => u.IsActive).HasColumnName("is_active"); entity.Property(u => u.CreatedAt).HasColumnName("created_at"); entity.Property(u => u.LastLoginAt).HasColumnName("last_login_at"); entity.Property(u => u.ThemePreference).HasColumnName("theme_preference"); entity.HasIndex(u => u.Email).IsUnique(); entity.HasIndex(u => u.Role); }); modelBuilder.Entity(entity => { entity.ToTable("user_device_tokens"); entity.Property(t => t.Id).HasColumnName("id"); entity.Property(t => t.UserId).HasColumnName("user_id"); entity.Property(t => t.FcmToken).HasColumnName("fcm_token"); entity.Property(t => t.DeviceName).HasColumnName("device_name"); entity.Property(t => t.RegisteredAt).HasColumnName("registered_at"); entity.Property(t => t.LastUsedAt).HasColumnName("last_used_at"); entity.HasIndex(t => t.UserId); entity.HasIndex(t => t.FcmToken); }); modelBuilder.Entity(entity => { entity.ToTable("user_favorite_assets"); entity.Property(f => f.Id).HasColumnName("id"); entity.Property(f => f.UserId).HasColumnName("user_id"); entity.Property(f => f.Isin).HasColumnName("isin"); entity.Property(f => f.CreatedAt).HasColumnName("created_at"); entity.HasIndex(f => new { f.UserId, f.Isin }).IsUnique(); }); modelBuilder.Entity(entity => { entity.ToTable("service_configurations"); entity.Property(c => c.Id).HasColumnName("id"); entity.Property(c => c.ServiceName).HasColumnName("service_name"); entity.Property(c => c.ConfigKey).HasColumnName("config_key"); entity.Property(c => c.ConfigValue).HasColumnName("config_value"); entity.Property(c => c.DataType).HasColumnName("data_type"); entity.Property(c => c.Description).HasColumnName("description"); entity.Property(c => c.UpdatedAt).HasColumnName("updated_at"); entity.HasIndex(c => new { c.ServiceName, c.ConfigKey }).IsUnique(); }); } } /// /// Lets `dotnet ef migrations add` construct a without booting the full /// application (which fails fast at startup if JWT_SECRET_KEY/ADMIN_DEFAULT_PASSWORD aren't set - see /// Program.cs) - the same pattern every other service's DbContext already uses /// (e.g. TechnicalAnalysisDbContextFactory). /// public class BackendDbContextFactory : IDesignTimeDbContextFactory { public BackendDbContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseNpgsql("Host=localhost;Database=finlytic_backend;Username=postgres;Password=postgres"); return new BackendDbContext(optionsBuilder.Options); } }