@@ -32,6 +32,9 @@ public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
|
||||
public DbSet<MessagingGroup> MessagingGroups => Set<MessagingGroup>();
|
||||
public DbSet<NotificationLog> NotificationLogs => Set<NotificationLog>();
|
||||
|
||||
public DbSet<SiteSetting> SiteSettings => Set<SiteSetting>();
|
||||
public DbSet<NotificationSetting> NotificationSettings => Set<NotificationSetting>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
@@ -245,12 +248,43 @@ public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
|
||||
entity.Property(e => e.BankName).HasMaxLength(200);
|
||||
entity.Property(e => e.BankAccountNumber).HasMaxLength(50);
|
||||
entity.Property(e => e.BankRoutingNumber).HasMaxLength(50);
|
||||
entity.Property(e => e.NameZh).HasMaxLength(200);
|
||||
entity.Property(e => e.Phone).HasMaxLength(50);
|
||||
entity.Property(e => e.Email).HasMaxLength(200);
|
||||
entity.Property(e => e.Website).HasMaxLength(300);
|
||||
entity.Property(e => e.CreatedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.UpdatedBy).HasMaxLength(450);
|
||||
// Optimistic-concurrency token for safe check-number allocation.
|
||||
entity.Property(e => e.xmin).IsRowVersion();
|
||||
});
|
||||
|
||||
// ── SiteSetting (singleton presentation/locale settings) ─────────────
|
||||
builder.Entity<SiteSetting>(entity =>
|
||||
{
|
||||
entity.Property(e => e.SiteTitle).HasMaxLength(200).IsRequired();
|
||||
entity.Property(e => e.SiteTitleZh).HasMaxLength(200);
|
||||
entity.Property(e => e.DefaultLanguage).HasMaxLength(10).IsRequired();
|
||||
entity.Property(e => e.TimeZone).HasMaxLength(100).IsRequired();
|
||||
entity.Property(e => e.DateFormat).HasMaxLength(50).IsRequired();
|
||||
entity.Property(e => e.Currency).HasMaxLength(10).IsRequired();
|
||||
entity.Property(e => e.CreatedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.UpdatedBy).HasMaxLength(450);
|
||||
});
|
||||
|
||||
// ── NotificationSetting (singleton SMTP + Line settings) ─────────────
|
||||
builder.Entity<NotificationSetting>(entity =>
|
||||
{
|
||||
entity.Property(e => e.SmtpHost).HasMaxLength(200);
|
||||
entity.Property(e => e.SmtpUser).HasMaxLength(200);
|
||||
entity.Property(e => e.SmtpPassword).HasMaxLength(500);
|
||||
entity.Property(e => e.FromAddress).HasMaxLength(200);
|
||||
entity.Property(e => e.FromName).HasMaxLength(200);
|
||||
entity.Property(e => e.LineChannelAccessToken).HasMaxLength(500);
|
||||
entity.Property(e => e.LineChannelSecret).HasMaxLength(200);
|
||||
entity.Property(e => e.CreatedBy).HasMaxLength(450);
|
||||
entity.Property(e => e.UpdatedBy).HasMaxLength(450);
|
||||
});
|
||||
|
||||
// ── Check (disbursement) ─────────────────────────────────────────────
|
||||
builder.Entity<Check>(entity =>
|
||||
{
|
||||
|
||||
@@ -208,6 +208,50 @@ public static class DbSeeder
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task SeedSiteSettingAsync(AppDbContext db)
|
||||
{
|
||||
// Singleton row holding site-wide presentation/locale settings.
|
||||
if (!await db.SiteSettings.AnyAsync())
|
||||
{
|
||||
db.SiteSettings.Add(new SiteSetting
|
||||
{
|
||||
SiteTitle = "River Of Life Christian Church",
|
||||
SiteTitleZh = "生命河靈糧堂",
|
||||
DefaultLanguage = "en",
|
||||
TimeZone = "America/Los_Angeles",
|
||||
DateFormat = "yyyy-MM-dd",
|
||||
Currency = "USD",
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task SeedNotificationSettingAsync(AppDbContext db, IConfiguration config)
|
||||
{
|
||||
// Singleton row that becomes the runtime source of truth for SMTP + Line. Seed it once
|
||||
// from the legacy "Smtp"/"Line" appsettings sections so existing config carries over.
|
||||
if (!await db.NotificationSettings.AnyAsync())
|
||||
{
|
||||
var smtp = config.GetSection("Smtp");
|
||||
var line = config.GetSection("Line");
|
||||
db.NotificationSettings.Add(new NotificationSetting
|
||||
{
|
||||
EnableEmail = !string.IsNullOrWhiteSpace(smtp["Host"]),
|
||||
SmtpHost = smtp["Host"] ?? "",
|
||||
SmtpPort = int.TryParse(smtp["Port"], out var port) ? port : 587,
|
||||
SmtpUseSsl = !bool.TryParse(smtp["UseSsl"], out var ssl) || ssl,
|
||||
SmtpUser = smtp["User"] ?? "",
|
||||
SmtpPassword = smtp["Password"] ?? "",
|
||||
FromAddress = smtp["FromAddress"] ?? "",
|
||||
FromName = smtp["FromName"] ?? "",
|
||||
EnableLine = !string.IsNullOrWhiteSpace(line["ChannelAccessToken"]),
|
||||
LineChannelAccessToken = line["ChannelAccessToken"] ?? "",
|
||||
LineChannelSecret = line["ChannelSecret"] ?? "",
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeds roles and (in Development) the default admin account.
|
||||
/// Called once on application startup after migrations have been applied.
|
||||
@@ -217,6 +261,7 @@ public static class DbSeeder
|
||||
var roleManager = services.GetRequiredService<RoleManager<AppRole>>();
|
||||
var userManager = services.GetRequiredService<UserManager<AppUser>>();
|
||||
var env = services.GetRequiredService<IWebHostEnvironment>();
|
||||
var config = services.GetRequiredService<IConfiguration>();
|
||||
|
||||
await SeedRolesAsync(roleManager);
|
||||
|
||||
@@ -226,6 +271,8 @@ public static class DbSeeder
|
||||
await SeedMinistriesAsync(db);
|
||||
await SeedExpenseCategoriesAsync(db);
|
||||
await SeedChurchProfileAsync(db);
|
||||
await SeedSiteSettingAsync(db);
|
||||
await SeedNotificationSettingAsync(db, config);
|
||||
|
||||
if (env.IsDevelopment())
|
||||
await SeedAdminUserAsync(userManager);
|
||||
|
||||
Reference in New Issue
Block a user