diff --git a/src/Meezi.Infrastructure/Data/PlatformDataSeeder.cs b/src/Meezi.Infrastructure/Data/PlatformDataSeeder.cs index 0500a87..7005983 100644 --- a/src/Meezi.Infrastructure/Data/PlatformDataSeeder.cs +++ b/src/Meezi.Infrastructure/Data/PlatformDataSeeder.cs @@ -33,6 +33,12 @@ public static class PlatformDataSeeder // from their city, so the public map lights up. Idempotent (fills nulls). await BackfillCafeLocationsAsync(db, logger); + // Subscription plans + feature flags are platform config the admin panel + // reads in every environment. Idempotent: adds any rows that are missing + // (so prod, which only had the Free plan, gets Pro/Business/Enterprise). + await SeedPlansAsync(db, logger); + await SeedFeaturesAsync(db, logger); + if (!env.IsDevelopment()) { // Production: also ensure integration settings (Kavenegar enabled/template, @@ -43,8 +49,6 @@ public static class PlatformDataSeeder await EnsureCatalogUpgradesAsync(db, logger); await SeedSystemAdminAsync(db, logger); - await SeedPlansAsync(db, logger); - await SeedFeaturesAsync(db, logger); await SeedSettingsAsync(db, logger); await EnsureIntegrationSettingsAsync(db, logger); } @@ -357,9 +361,6 @@ public static class PlatformDataSeeder private static async Task SeedPlansAsync(AppDbContext db, ILogger logger) { - if (await db.PlatformPlanDefinitions.AnyAsync()) - return; - var plans = new[] { new PlatformPlanDefinition @@ -421,16 +422,18 @@ public static class PlatformDataSeeder } }; - db.PlatformPlanDefinitions.AddRange(plans); + var existingIds = (await db.PlatformPlanDefinitions.Select(p => p.Id).ToListAsync()) + .ToHashSet(StringComparer.Ordinal); + var missing = plans.Where(p => !existingIds.Contains(p.Id)).ToArray(); + if (missing.Length == 0) return; + + db.PlatformPlanDefinitions.AddRange(missing); await db.SaveChangesAsync(); - logger.LogInformation("Platform seed: {Count} subscription plans", plans.Length); + logger.LogInformation("Platform seed: +{Count} subscription plans", missing.Length); } private static async Task SeedFeaturesAsync(AppDbContext db, ILogger logger) { - if (await db.PlatformFeatures.AnyAsync()) - return; - var features = new[] { F("pos", "صندوق", "POS", "core"), @@ -456,9 +459,14 @@ public static class PlatformDataSeeder F("discover_profile", "پروفایل کشف", "Discover profile", "growth") }; - db.PlatformFeatures.AddRange(features); + var existingIds = (await db.PlatformFeatures.Select(f => f.Id).ToListAsync()) + .ToHashSet(StringComparer.Ordinal); + var missing = features.Where(f => !existingIds.Contains(f.Id)).ToArray(); + if (missing.Length == 0) return; + + db.PlatformFeatures.AddRange(missing); await db.SaveChangesAsync(); - logger.LogInformation("Platform seed: {Count} feature flags", features.Length); + logger.LogInformation("Platform seed: +{Count} feature flags", missing.Length); } private static PlatformFeature F(string key, string fa, string en, string group) => new() diff --git a/web/admin/src/components/admin/admin-screens.tsx b/web/admin/src/components/admin/admin-screens.tsx index 61c41a2..2e18089 100644 --- a/web/admin/src/components/admin/admin-screens.tsx +++ b/web/admin/src/components/admin/admin-screens.tsx @@ -44,6 +44,7 @@ function Toggle({ checked, onChange, disabled }: { checked: boolean; onChange: (