From f5ba73f8753c39157dd388c8b3a543b16536bb1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Mon, 17 Aug 2026 12:23:47 +0300 Subject: [PATCH] =?UTF-8?q?seeds=20klas=C3=B6r=20yap=C4=B1s=C4=B1=20de?= =?UTF-8?q?=C4=9Fi=C5=9Fikli=C4=9Fi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 ++++++-- .../ISqlObjectManagerAppService.cs | 6 +- .../SqlExecutionDto.cs | 6 +- .../SqlObjectManagerAppService.cs | 21 ++--- .../ListForms/Wizard/WizardSeedFileDto.cs | 2 +- .../ListForms/ListFormWizardAppService.cs | 7 +- .../AfterAllMigrationsSqlExecutor.cs | 28 +++---- .../Migrations/SqlDataSeeder.cs | 62 ++++++-------- .../Migrations/WizardDataSeeder.cs | 10 ++- .../Data/PlatformDbMigrationService.cs | 9 +- .../Data/SeedPathResolver.cs | 83 ++++++++++++++++--- configs/seeds/host/crud/.gitkeep | 0 configs/seeds/host/custom/.gitkeep | 0 configs/seeds/host/postgres/execute/.gitkeep | 0 ...ieldsDictionaryJson_SaveDbTableColumns.sql | 0 configs/seeds/host/postgres/object/.gitkeep | 0 .../object}/Adm_T_DatabaseBackupAll.sql | 0 .../Adm_T_DatabaseBackupFilesDeleteAll.sql | 0 .../Sas_H_BackgroundWorker_JobFlow.sql | 0 .../Sas_H_ListFormFieldsDictionaryJson.sql | 0 .../object}/Sas_H_OrderItem_ByTenantId.sql | 0 configs/seeds/host/sql/execute/.gitkeep | 0 ...ieldsDictionaryJson_SaveDbTableColumns.sql | 0 configs/seeds/host/sql/object/.gitkeep | 0 .../sql/object}/Adm_T_DatabaseBackupAll.sql | 0 .../Adm_T_DatabaseBackupFilesDeleteAll.sql | 0 .../Sas_H_BackgroundWorker_JobFlow.sql | 0 .../Sas_H_ListFormFieldsDictionaryJson.sql | 0 .../object}/Sas_H_OrderItem_ByTenantId.sql | 0 configs/seeds/host/wizard/.gitkeep | 0 configs/seeds/tenants/.gitkeep | 0 31 files changed, 165 insertions(+), 103 deletions(-) create mode 100644 configs/seeds/host/crud/.gitkeep create mode 100644 configs/seeds/host/custom/.gitkeep create mode 100644 configs/seeds/host/postgres/execute/.gitkeep rename configs/seeds/{PostgresData/HostData/ExecuteData => host/postgres/execute}/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql (100%) create mode 100644 configs/seeds/host/postgres/object/.gitkeep rename configs/seeds/{PostgresData/HostData/ObjectData => host/postgres/object}/Adm_T_DatabaseBackupAll.sql (100%) rename configs/seeds/{PostgresData/HostData/ObjectData => host/postgres/object}/Adm_T_DatabaseBackupFilesDeleteAll.sql (100%) rename configs/seeds/{PostgresData/HostData/ObjectData => host/postgres/object}/Sas_H_BackgroundWorker_JobFlow.sql (100%) rename configs/seeds/{PostgresData/HostData/ObjectData => host/postgres/object}/Sas_H_ListFormFieldsDictionaryJson.sql (100%) rename configs/seeds/{PostgresData/HostData/ObjectData => host/postgres/object}/Sas_H_OrderItem_ByTenantId.sql (100%) create mode 100644 configs/seeds/host/sql/execute/.gitkeep rename configs/seeds/{SqlData/HostData/ExecuteData => host/sql/execute}/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql (100%) create mode 100644 configs/seeds/host/sql/object/.gitkeep rename configs/seeds/{SqlData/HostData/ObjectData => host/sql/object}/Adm_T_DatabaseBackupAll.sql (100%) rename configs/seeds/{SqlData/HostData/ObjectData => host/sql/object}/Adm_T_DatabaseBackupFilesDeleteAll.sql (100%) rename configs/seeds/{SqlData/HostData/ObjectData => host/sql/object}/Sas_H_BackgroundWorker_JobFlow.sql (100%) rename configs/seeds/{SqlData/HostData/ObjectData => host/sql/object}/Sas_H_ListFormFieldsDictionaryJson.sql (100%) rename configs/seeds/{SqlData/HostData/ObjectData => host/sql/object}/Sas_H_OrderItem_ByTenantId.sql (100%) create mode 100644 configs/seeds/host/wizard/.gitkeep create mode 100644 configs/seeds/tenants/.gitkeep diff --git a/README.md b/README.md index 43ccfd0e..b8a69b59 100644 --- a/README.md +++ b/README.md @@ -178,8 +178,10 @@ sozsoft-platform/ ├── configs/ │ ├── docker/ # Yerel geliştirme için veri katmanı compose dosyaları ve scriptler │ ├── deployment/ # Dev/Prod compose dosyaları, nginx/redis/turn konfigürasyonu, deploy scriptleri -│ ├── seeds/ # Runtime'da düzenlenebilen seed'ler: SqlData, PostgresData, WizardData -│ │ # {SqlData|PostgresData}/{HostData|TenantData}/{ObjectData|ExecuteData} +│ ├── seeds/ # Runtime'da düzenlenebilen seed'ler; CDN ile aynı kapsam düzeni +│ │ # host/{crud,custom,wizard,sql,postgres} +│ │ # tenants/{tenantId}/{crud,custom,wizard,sql,postgres} +│ │ # {sql|postgres}/{object,execute} │ └── ai/ # AI entegrasyonu (n8n akış tanımları) ├── .github/instructions/ # ai.instructions.md (bağlayıcı platform kuralları), list.instructions.md ├── CLAUDE.md # Claude Code için operasyon kuralları @@ -238,14 +240,32 @@ host ayarları, ülke/şehir/ilçe verileri ile seed edilmiş ListForm ekranlar (kodla versiyonlanan sabit seed'ler `api/src/Sozsoft.Platform.DbMigrator/Migrations/`, runtime'da düzenlenebilen seed'ler `configs/seeds/` altındadır — bkz. `App:SeedsPath`). -`configs/seeds/{SqlData|PostgresData}` altındaki her `.sql` dosyası, önce veritabanı -kapsamına (`HostData` / `TenantData`), sonra amacına göre bir klasörde durur; klasör -köklerinde dosya bulunmaz: +`configs/seeds` altında en üst seviye kapsamdır (CDN klasörleriyle aynı mantık): host +veritabanı için `host/`, her tenant için `tenants/{tenantId}/`. Kapsamın altında içerik +türüne göre `crud/`, `custom/`, `wizard/`, `sql/`, `postgres/` klasörleri bulunur: + +``` +configs/seeds/ + host/ + crud/ custom/ wizard/ + sql/ { object/ execute/ } + postgres/ { object/ execute/ } + tenants/ + {tenantId}/ + crud/ custom/ wizard/ + sql/ { object/ execute/ } + postgres/ { object/ execute/ } +``` + +Aktif veritabanı sağlayıcısına göre `sql/` (SQL Server) ya da `postgres/` okunur. Her +`.sql` dosyası amacını belirten bir klasörün altındadır; klasör köklerinde dosya bulunmaz: | Klasör | Ne zaman çalışır | | --- | --- | -| `{HostData\|TenantData}/ObjectData` | Seed sırasında nesneyi oluşturur/günceller. SqlTableDesigner ve SqlQueryManager, deploy ettiği script'i çalıştığı kapsamın bu klasörüne yazar (host bağlamı → `HostData`, tenant seçiliyken → `TenantData`). | -| `{HostData\|TenantData}/ExecuteData` | Nesneyi oluşturur; ayrıca tüm migration ve seed'ler bittikten sonra `AfterAllMigrationsSqlExecutor` dosya adından türettiği procedure'ü çalıştırır (dosya adı = procedure adı, `schema.Procedure.sql` de olur). | +| `{sql\|postgres}/object` | Seed sırasında nesneyi oluşturur/günceller. SqlTableDesigner ve SqlQueryManager, deploy ettiği script'i çalıştığı kapsamın bu klasörüne yazar (host bağlamı → `host/`, tenant seçiliyken → `tenants/{tenantId}/`). | +| `{sql\|postgres}/execute` | Nesneyi oluşturur; ayrıca tüm migration ve seed'ler bittikten sonra `AfterAllMigrationsSqlExecutor` dosya adından türettiği procedure'ü çalıştırır (dosya adı = procedure adı, `schema.Procedure.sql` de olur). | +| `wizard` | ListForm Wizard'ın ürettiği `.json` konfigürasyonları; `WizardDataSeeder` kendi kapsamındaki dosyaları okur. | +| `crud` / `custom` | CrudEndpoint ve CustomEndpoint konfigürasyonları için ayrılmıştır. | Klasör kökünde kalmış eski `.sql` dosyaları geriye dönük uyumluluk için hâlâ işlenir, fakat `SqlDataSeeder` bunları uyarı ile loglar — ilgili klasöre taşınmaları beklenir. diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/ISqlObjectManagerAppService.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/ISqlObjectManagerAppService.cs index 8b84af5d..aaf75270 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/ISqlObjectManagerAppService.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/ISqlObjectManagerAppService.cs @@ -30,14 +30,14 @@ public interface ISqlObjectManagerAppService : IApplicationService Task GetNativeObjectDefinitionAsync(string dataSourceCode, string schemaName, string objectName); /// - /// Saves the T-SQL script to {SeedsRoot}/{SqlData|PostgresData}/{HostData|TenantData}/ObjectData/{fileName}.sql - /// (repo: configs/seeds). The scope folder follows the current tenant: host context writes to HostData. + /// Saves the T-SQL script to {SeedsRoot}/{host|tenants/{tenantId}}/{sql|postgres}/object/{fileName}.sql + /// (repo: configs/seeds). The scope folder follows the current tenant: host context writes to host/. /// Called automatically after a successful SqlTableDesigner deploy so the script can be re-seeded. /// Task SaveTableScriptAsync(SaveTableScriptDto input); /// - /// Deletes matching SQL seed files from the current scope's ObjectData folder when objects are + /// Deletes matching SQL seed files from the current scope's object folder when objects are /// dropped from the UI. /// Non-existing files are ignored. /// diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlExecutionDto.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlExecutionDto.cs index 7927dffc..6b8dd9af 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlExecutionDto.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application.Contracts/SqlExecutionDto.cs @@ -20,7 +20,8 @@ public class SqlQueryExecutionResultDto } /// -/// Input for saving a T-SQL script file to the seeds folder ({App:SeedsPath}/SqlData). +/// Input for saving a T-SQL script file to the seeds folder +/// ({App:SeedsPath}/{host|tenants/{tenantId}}/{sql|postgres}/object). /// public class SaveTableScriptDto { @@ -36,7 +37,8 @@ public class SaveTableScriptDto } /// -/// Input for deleting seed files from the seeds folder ({App:SeedsPath}/SqlData). +/// Input for deleting seed files from the seeds folder +/// ({App:SeedsPath}/{host|tenants/{tenantId}}/{sql|postgres}/object). /// public class DeleteSqlDataFilesDto { diff --git a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlObjectManagerAppService.cs b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlObjectManagerAppService.cs index 8d210168..2008d682 100644 --- a/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlObjectManagerAppService.cs +++ b/api/modules/Sozsoft.SqlQueryManager/Sozsoft.SqlQueryManager.Application/SqlObjectManagerAppService.cs @@ -962,26 +962,21 @@ FROM ( /// (App:SeedsPath -> configs/seeds), aksi halde deploy edilen nesne seed olarak geri okunmaz. /// /// Yol, islemin yapildigi veritabani kapsamini izler: host (varsayilan) baglaminda - /// {SqlData|PostgresData}/HostData/ObjectData, bir tenant secilmisken - /// {SqlData|PostgresData}/TenantData/ObjectData. Boylece nesne, seed sirasinda + /// host/{sql|postgres}/object, bir tenant secilmisken + /// tenants/{tenantId}/{sql|postgres}/object. Boylece nesne, seed sirasinda /// olusturuldugu veritabaninda yeniden olusturulur. /// /// private string ResolveSqlDataOutputPath() { - var dataDirectoryName = SettingsConsts.DefaultDatabaseProvider == SettingsConsts.DatabaseProvider.PostgreSql - ? SeedPathResolver.PostgresDataFolder - : SeedPathResolver.SqlDataFolder; + var providerDirectoryName = SeedPathResolver.GetProviderFolderName( + SettingsConsts.DefaultDatabaseProvider == SettingsConsts.DatabaseProvider.PostgreSql); - var scopeDirectoryName = _currentTenant.Id == null - ? SeedPathResolver.HostDataFolder - : SeedPathResolver.TenantDataFolder; - - return SeedPathResolver.GetPath( + return SeedPathResolver.GetScopePath( _configuration, - dataDirectoryName, - scopeDirectoryName, - SeedPathResolver.ObjectDataFolder); + _currentTenant.Id, + providerDirectoryName, + SeedPathResolver.ObjectFolder); } } diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Wizard/WizardSeedFileDto.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Wizard/WizardSeedFileDto.cs index 86242345..f4aa2f2c 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Wizard/WizardSeedFileDto.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Wizard/WizardSeedFileDto.cs @@ -4,7 +4,7 @@ namespace Sozsoft.Platform.ListForms; /// /// Wizard seed dosyası formatı. -/// WizardAppService tarafından Seeds/WizardData/{wizardName}.json olarak kaydedilir. +/// WizardAppService tarafından Seeds/{host|tenants/{tenantId}}/wizard/{wizardName}.json olarak kaydedilir. /// WizardDataSeeder (DbMigrator) bu dosyaları okuyarak veritabanını yeniden oluşturur. /// public class WizardSeedFileDto diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs index 6116c54e..e061253a 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs @@ -535,7 +535,7 @@ public class ListFormWizardAppService( /// /// Wizard konfigürasyonunu JSON dosyası olarak kaydeder. - /// Dosya, seeder'lar ve File Manager ile ortak olan seed klasörünün WizardData dizinine yazılır. + /// Dosya, seeder'lar ve File Manager ile ortak olan seed klasörünün wizard dizinine yazılır. /// Veritabanı silinip yeniden oluşturulduğunda WizardDataSeeder bu dosyaları okuyarak konfigürasyonu geri yükler. /// private async Task SaveWizardSeedFileAsync(ListFormWizardDto input, bool isDeletedField, bool isCreatedField, WizardInsertedRecordsDto inserted) @@ -758,12 +758,13 @@ public class ListFormWizardAppService( } /// - /// Wizard seed dosyalarinin yazilacagi WizardData dizinini dondurur. + /// Wizard seed dosyalarinin yazilacagi wizard dizinini dondurur; kapsam aktif tenant'i izler + /// (host baglaminda host/wizard, tenant baglaminda tenants/{tenantId}/wizard). /// Yol cozumu uzerinden seeder'lar ve File Manager ile ortaktir. /// private string ResolveWizardSeedOutputPath() { - return SeedPathResolver.GetPath(_configuration, "WizardData"); + return SeedPathResolver.GetScopePath(_configuration, CurrentTenant.Id, SeedPathResolver.WizardFolder); } private async Task> GetTableColumnNamesAsync(string dataSourceCode, SelectCommandTypeEnum commandType, string selectCommand) diff --git a/api/src/Sozsoft.Platform.DbMigrator/Migrations/AfterAllMigrationsSqlExecutor.cs b/api/src/Sozsoft.Platform.DbMigrator/Migrations/AfterAllMigrationsSqlExecutor.cs index f8bb145a..1bfa208b 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Migrations/AfterAllMigrationsSqlExecutor.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Migrations/AfterAllMigrationsSqlExecutor.cs @@ -16,24 +16,18 @@ using static Sozsoft.Settings.SettingsConsts; namespace Sozsoft.Platform.Data.Seeds; /// -/// Seeds/{SqlData|PostgresData}/{HostData|TenantData}/ExecuteData klasöründeki .sql dosyaları +/// Seeds/{host|tenants/{tenantId}}/{sql|postgres}/execute klasöründeki .sql dosyaları /// iki aşamada işlenir: -/// 1) Migration/seed sırasında tarafından, üst klasörle (HostData/TenantData) -/// aynı kapsamda çalıştırılır (nesne oluşturulur/güncellenir). +/// 1) Migration/seed sırasında tarafından, kapsam klasörüyle +/// (host/tenants/{tenantId}) aynı bağlamda çalıştırılır (nesne oluşturulur/güncellenir). /// 2) Tüm migration ve seed işlemleri bittikten sonra bu sınıf, dosya adından türetilen stored /// procedure'ü ilgili bağlamda (host ya da tenant) varlığı doğrulanarak çalıştırır. /// Dosya adı = procedure adı. İsteğe bağlı olarak "schema.Procedure.sql" formatı da desteklenir. /// public class AfterAllMigrationsSqlExecutor : IAfterAllMigrationsSqlExecutor, ITransientDependency { - /// HostData/TenantData altındaki, migration sonrası da çalıştırılacak script klasörünün adı. - public const string DirectoryName = SeedPathResolver.ExecuteDataFolder; - - /// Host kapsamındaki script klasörü. - public const string HostDataDirectoryName = SeedPathResolver.HostDataFolder; - - /// Tenant kapsamındaki script klasörü (henüz kullanılmıyorsa sessizce atlanır). - public const string TenantDataDirectoryName = SeedPathResolver.TenantDataFolder; + /// {sql|postgres} altındaki, migration sonrası da çalıştırılacak script klasörünün adı. + public const string DirectoryName = SeedPathResolver.ExecuteFolder; private static readonly Regex SafeIdentifierRegex = new(@"^[A-Za-z_][A-Za-z0-9_]{0,126}$", RegexOptions.Compiled); @@ -57,8 +51,7 @@ public class AfterAllMigrationsSqlExecutor : IAfterAllMigrationsSqlExecutor, ITr public async Task ExecuteAsync(Guid? tenantId = null) { - var scopeDirectoryName = tenantId == null ? HostDataDirectoryName : TenantDataDirectoryName; - var directoryPath = GetScriptDirectoryPath(scopeDirectoryName); + var directoryPath = GetScriptDirectoryPath(tenantId); if (!Directory.Exists(directoryPath)) { @@ -135,13 +128,12 @@ public class AfterAllMigrationsSqlExecutor : IAfterAllMigrationsSqlExecutor, ITr } } - private string GetScriptDirectoryPath(string scopeDirectoryName) + private string GetScriptDirectoryPath(Guid? tenantId) { - var dataDirectoryName = DefaultDatabaseProvider == DatabaseProvider.PostgreSql - ? SeedPathResolver.PostgresDataFolder - : SeedPathResolver.SqlDataFolder; + var providerDirectoryName = SeedPathResolver.GetProviderFolderName( + DefaultDatabaseProvider == DatabaseProvider.PostgreSql); - return SeedPathResolver.GetPath(_configuration, dataDirectoryName, scopeDirectoryName, DirectoryName); + return SeedPathResolver.GetScopePath(_configuration, tenantId, providerDirectoryName, DirectoryName); } /// diff --git a/api/src/Sozsoft.Platform.DbMigrator/Migrations/SqlDataSeeder.cs b/api/src/Sozsoft.Platform.DbMigrator/Migrations/SqlDataSeeder.cs index 4d416dec..0203d08d 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Migrations/SqlDataSeeder.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Migrations/SqlDataSeeder.cs @@ -17,21 +17,23 @@ namespace Sozsoft.Platform.Data.Seeds; /// /// SqlTableDesigner ve SqlQueryManager üzerinden deploy edilen nesneleri -/// {SqlData|PostgresData} klasöründeki .sql dosyalarından okuyarak veritabanına uygular. +/// {host|tenants/{tenantId}}/{sql|postgres} klasöründeki .sql dosyalarından okuyarak +/// veritabanına uygular. /// Her dosya, tek bir nesneye (ve ilgili ALTER/INDEX script'lerine) ait varlık kontrolü içeren /// batch'lerden oluşmalıdır. Veritabanı silinip yeniden oluşturulduğunda tüm scriptler yeniden çalışır. /// /// Klasör düzeni — her .sql dosyası amacını belirten bir klasörün altındadır, kökte dosya durmaz: /// -/// {SqlData|PostgresData}/ -/// HostData/ → host (varsayılan) veritabanı kapsamı -/// ObjectData/ → nesne oluşturulur/güncellenir. SqlTableDesigner ve +/// host/ → host (varsayılan) veritabanı kapsamı +/// {sql|postgres}/ +/// object/ → nesne oluşturulur/güncellenir. SqlTableDesigner ve /// SqlQueryManager, host bağlamındayken buraya yazar. -/// ExecuteData/ → nesne oluşturulur, ayrıca tüm migration'lar bittikten sonra +/// execute/ → nesne oluşturulur, ayrıca tüm migration'lar bittikten sonra /// tarafından çalıştırılır. -/// TenantData/ → tenant veritabanı kapsamı (bir tenant seçiliyken üretilenler) -/// ObjectData/ -/// ExecuteData/ +/// tenants/{tenantId}/ → ilgili tenant veritabanı kapsamı +/// {sql|postgres}/ +/// object/ +/// execute/ /// /// Geriye dönük uyumluluk: klasör köklerinde kalmış eski .sql dosyaları da işlenir, ancak /// uyarı ile loglanır — taşınmaları beklenir. @@ -40,7 +42,7 @@ namespace Sozsoft.Platform.Data.Seeds; public class SqlDataSeeder : IDataSeedContributor, ITransientDependency { /// Yalnızca oluşturulan/güncellenen nesne scriptlerinin klasörü. - public const string ObjectDataDirectoryName = SeedPathResolver.ObjectDataFolder; + public const string ObjectDirectoryName = SeedPathResolver.ObjectFolder; private readonly IDbContextProvider _dbContextProvider; private readonly IConfiguration _configuration; @@ -58,16 +60,15 @@ public class SqlDataSeeder : IDataSeedContributor, ITransientDependency public async Task SeedAsync(DataSeedContext context) { - var dataDirectoryName = GetDataDirectoryName(); - var sqlDataPath = SeedPathResolver.GetPath(_configuration, dataDirectoryName); + var dataDirectoryName = $"{SeedPathResolver.GetScopeFolderName(context.TenantId)}/{GetProviderDirectoryName()}"; + var sqlDataPath = SeedPathResolver.GetScopePath(_configuration, context.TenantId, GetProviderDirectoryName()); if (!Directory.Exists(sqlDataPath)) { _logger.LogInformation("Seeds/{DirectoryName} directory not found, skipping SqlDataSeeder.", dataDirectoryName); return; } - var isHostSeed = context.TenantId == null; - var sqlFiles = GetSqlFiles(sqlDataPath, isHostSeed); + var sqlFiles = GetSqlFiles(sqlDataPath); if (sqlFiles.Length == 0) { @@ -79,7 +80,7 @@ public class SqlDataSeeder : IDataSeedContributor, ITransientDependency "SqlDataSeeder started for provider '{Provider}' from Seeds/{DirectoryName}. Seed target: {SeedTarget}. {Count} file(s) to be processed.", DefaultDatabaseProvider, dataDirectoryName, - isHostSeed ? "Host" : "Tenant", + context.TenantId == null ? "Host" : $"Tenant {context.TenantId}", sqlFiles.Length); var dbContext = await _dbContextProvider.GetDbContextAsync(); @@ -129,35 +130,24 @@ public class SqlDataSeeder : IDataSeedContributor, ITransientDependency _logger.LogInformation("SqlDataSeeder completed. {Count} file(s) processed.", sqlFiles.Length); } - private static string GetDataDirectoryName() + private static string GetProviderDirectoryName() { - return DefaultDatabaseProvider == DatabaseProvider.PostgreSql - ? SeedPathResolver.PostgresDataFolder - : SeedPathResolver.SqlDataFolder; + return SeedPathResolver.GetProviderFolderName(DefaultDatabaseProvider == DatabaseProvider.PostgreSql); } - private string[] GetSqlFiles(string dataDirectoryPath, bool isHostSeed) + private string[] GetSqlFiles(string providerDirectoryPath) { var sqlFiles = new List(); // Klasor kokunde dosya beklenmez; eskiden kalanlar uyari ile islenir. - sqlFiles.AddRange(GetLegacyRootSqlFiles(dataDirectoryPath)); + sqlFiles.AddRange(GetLegacyRootSqlFiles(providerDirectoryPath)); - var scopeDirectoryName = isHostSeed - ? AfterAllMigrationsSqlExecutor.HostDataDirectoryName - : AfterAllMigrationsSqlExecutor.TenantDataDirectoryName; + sqlFiles.AddRange(GetOrderedSqlFiles(Path.Combine(providerDirectoryPath, ObjectDirectoryName))); - var scopePath = Path.Combine(dataDirectoryPath, scopeDirectoryName); - if (Directory.Exists(scopePath)) - { - sqlFiles.AddRange(GetOrderedSqlFiles(Path.Combine(scopePath, ObjectDataDirectoryName))); - sqlFiles.AddRange(GetLegacyRootSqlFiles(scopePath)); - - // {HostData|TenantData}/ExecuteData: nesneler burada da oluşturulur, ayrıca tüm - // migration bittikten sonra AfterAllMigrationsSqlExecutor dosya adı üzerinden çalıştırır. - sqlFiles.AddRange(GetOrderedSqlFiles( - Path.Combine(scopePath, AfterAllMigrationsSqlExecutor.DirectoryName))); - } + // {sql|postgres}/execute: nesneler burada da oluşturulur, ayrıca tüm migration + // bittikten sonra AfterAllMigrationsSqlExecutor dosya adı üzerinden çalıştırır. + sqlFiles.AddRange(GetOrderedSqlFiles( + Path.Combine(providerDirectoryPath, AfterAllMigrationsSqlExecutor.DirectoryName))); return sqlFiles.ToArray(); } @@ -179,10 +169,10 @@ public class SqlDataSeeder : IDataSeedContributor, ITransientDependency if (files.Length > 0) { _logger.LogWarning( - "{Count} .sql file(s) found directly under '{Directory}'. Move them into the '{ObjectData}' folder; root-level files are deprecated.", + "{Count} .sql file(s) found directly under '{Directory}'. Move them into the '{ObjectFolder}' folder; root-level files are deprecated.", files.Length, directoryPath, - ObjectDataDirectoryName); + ObjectDirectoryName); } return files; diff --git a/api/src/Sozsoft.Platform.DbMigrator/Migrations/WizardDataSeeder.cs b/api/src/Sozsoft.Platform.DbMigrator/Migrations/WizardDataSeeder.cs index 4ce5373d..dcacfc0f 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Migrations/WizardDataSeeder.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Migrations/WizardDataSeeder.cs @@ -22,7 +22,8 @@ using static Sozsoft.Platform.PlatformConsts; namespace Sozsoft.Platform.Data.Seeds; /// -/// Wizard ile oluşturulan konfigürasyonları Seeds/WizardData/*.json dosyalarından okuyarak veritabanına aktarır. +/// Wizard ile oluşturulan konfigürasyonları Seeds/{host|tenants/{tenantId}}/wizard/*.json +/// dosyalarından okuyarak veritabanına aktarır (kapsam, seed edilen veritabanını izler). /// Wizard çalıştıktan sonra oluşturulan JSON dosyaları projeye commit edildikten sonra, /// veritabanı silinip yeniden oluşturulduğunda bu seeder tüm wizard konfigürasyonlarını geri yükler. /// @@ -71,17 +72,18 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency public async Task SeedAsync(DataSeedContext context) { - var wizardDataPath = SeedPathResolver.GetPath(_configuration, "WizardData"); + var scopeFolderName = SeedPathResolver.GetScopeFolderName(context.TenantId); + var wizardDataPath = SeedPathResolver.GetScopePath(_configuration, context.TenantId, SeedPathResolver.WizardFolder); if (!Directory.Exists(wizardDataPath)) { - _logger.LogInformation("WizardData directory not found, skipping."); + _logger.LogInformation("Seeds/{Scope}/wizard directory not found, skipping.", scopeFolderName); return; } var jsonFiles = Directory.GetFiles(wizardDataPath, "*.json").OrderBy(f => Path.GetFileName(f)).ToArray(); if (jsonFiles.Length == 0) { - _logger.LogInformation("No JSON files found in WizardData directory, skipping."); + _logger.LogInformation("No JSON files found in Seeds/{Scope}/wizard directory, skipping.", scopeFolderName); return; } diff --git a/api/src/Sozsoft.Platform.Domain/Data/PlatformDbMigrationService.cs b/api/src/Sozsoft.Platform.Domain/Data/PlatformDbMigrationService.cs index 59149844..d5efb3c9 100644 --- a/api/src/Sozsoft.Platform.Domain/Data/PlatformDbMigrationService.cs +++ b/api/src/Sozsoft.Platform.Domain/Data/PlatformDbMigrationService.cs @@ -110,15 +110,16 @@ public class PlatformDbMigrationService : ITransientDependency } /// - /// Tüm host ve tenant migration/seed adımları bittikten sonra, {HostData|TenantData}/ExecuteData - /// klasöründeki script'lerin dosya adından türeyen procedure'lerini ilgili bağlamda çalıştırır. - /// TenantData klasörü yoksa tenant adımı sessizce atlanır. + /// Tüm host ve tenant migration/seed adımları bittikten sonra, + /// {host|tenants/{tenantId}}/{sql|postgres}/execute klasöründeki script'lerin dosya adından + /// türeyen procedure'lerini ilgili bağlamda çalıştırır. İlgili tenant klasörü yoksa + /// o tenant adımı sessizce atlanır. /// private async Task ExecuteAfterAllMigrationsSqlAsync(List tenants) { if (!_afterAllMigrationsSqlExecutors.Any()) { - Logger.LogInformation("No SQL executor registered, skipping ExecuteData scripts."); + Logger.LogInformation("No SQL executor registered, skipping execute scripts."); return; } diff --git a/api/src/Sozsoft.Platform.Domain/Data/SeedPathResolver.cs b/api/src/Sozsoft.Platform.Domain/Data/SeedPathResolver.cs index 4114fe11..6b71d945 100644 --- a/api/src/Sozsoft.Platform.Domain/Data/SeedPathResolver.cs +++ b/api/src/Sozsoft.Platform.Domain/Data/SeedPathResolver.cs @@ -1,11 +1,13 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using Microsoft.Extensions.Configuration; namespace Sozsoft.Platform.Data.Seeds; /// -/// Runtime'da duzenlenebilen seed dosyalarinin (SqlData / PostgresData / WizardData) klasorunu cozer. +/// Runtime'da duzenlenebilen seed dosyalarinin klasorunu cozer. /// /// Kod ile birlikte versiyonlanan sabit seed'ler (ornegin TenantDataSeeder'in okudugu /// TenantData.json) buraya dahil degildir; onlar kendi projelerinin ciktisinda kalir. @@ -17,6 +19,25 @@ namespace Sozsoft.Platform.Data.Seeds; /// uzerinden de duzenlenebildigi icin yapilan degisiklik dogrudan host diskinde kalici olur. /// /// +/// Klasor duzeni CDN ile ayni kapsam mantigini izler — once kapsam, sonra icerik turu: +/// +/// seeds/ +/// host/ → host (varsayilan) veritabani kapsami +/// crud/ +/// custom/ +/// wizard/ +/// sql/ → SQL Server saglayicisi +/// object/ → nesne olusturulur/guncellenir +/// execute/ → nesne olusturulur, ayrica tum migration'lar bitince calistirilir +/// postgres/ → PostgreSQL saglayicisi +/// object/ +/// execute/ +/// tenants/ +/// {tenantId}/ → her tenant kendi klasorunde +/// crud/ custom/ wizard/ sql/{object,execute}/ postgres/{object,execute}/ +/// +/// +/// /// Cozum sirasi: /// 1) App:SeedsPath ayari (konteynerde mount noktasi), /// 2) calisma dizininden yukari dogru configs/seeds aramasi (local gelistirme), @@ -27,26 +48,32 @@ public static class SeedPathResolver { public const string ConfigurationKey = "App:SeedsPath"; + /// Host veritabani kapsamindaki seed'lerin kok klasoru. + public const string HostFolder = "host"; + + /// Tenant kapsamindaki seed'lerin kok klasoru; altinda tenant Id'si ile klasorler bulunur. + public const string TenantsFolder = "tenants"; + /// SQL Server saglayicisinin script klasoru. - public const string SqlDataFolder = "SqlData"; + public const string SqlFolder = "sql"; /// PostgreSQL saglayicisinin script klasoru. - public const string PostgresDataFolder = "PostgresData"; - - /// Host veritabani kapsamindaki scriptler. - public const string HostDataFolder = "HostData"; - - /// Tenant veritabani kapsamindaki scriptler. - public const string TenantDataFolder = "TenantData"; + public const string PostgresFolder = "postgres"; /// Yalnizca olusturulan/guncellenen nesne scriptleri. - public const string ObjectDataFolder = "ObjectData"; + public const string ObjectFolder = "object"; /// Olusturulan, ayrica tum migration'lar bittikten sonra calistirilan scriptler. - public const string ExecuteDataFolder = "ExecuteData"; + public const string ExecuteFolder = "execute"; /// Wizard'in urettigi konfigurasyon dosyalari. - public const string WizardDataFolder = "WizardData"; + public const string WizardFolder = "wizard"; + + /// Crud endpoint konfigurasyon dosyalari. + public const string CrudFolder = "crud"; + + /// Custom endpoint konfigurasyon dosyalari. + public const string CustomFolder = "custom"; private const string RepositorySeedsFolder = "seeds"; private const string RepositoryConfigsFolder = "configs"; @@ -83,6 +110,38 @@ public static class SeedPathResolver return path; } + /// + /// Kapsam klasorunun (host ya da ilgili tenant) altindaki yolu dondurur. + /// null ise host/, aksi halde tenants/{tenantId}/ kullanilir. + /// + public static string GetScopePath(IConfiguration? configuration, Guid? tenantId, params string[] subPaths) + { + return GetPath(configuration, BuildScopeSubPaths(tenantId, subPaths)); + } + + /// Kapsam klasorunun seed koküne gore goreli adi (host ya da tenants/{tenantId}). + public static string GetScopeFolderName(Guid? tenantId) + { + return tenantId == null + ? HostFolder + : $"{TenantsFolder}/{tenantId.Value}"; + } + + /// Aktif veritabani saglayicisina karsilik gelen script klasorunun adi. + public static string GetProviderFolderName(bool isPostgreSql) + { + return isPostgreSql ? PostgresFolder : SqlFolder; + } + + private static string[] BuildScopeSubPaths(Guid? tenantId, string[] subPaths) + { + var scopeSegments = tenantId == null + ? new[] { HostFolder } + : new[] { TenantsFolder, tenantId.Value.ToString() }; + + return scopeSegments.Concat(subPaths ?? Array.Empty()).ToArray(); + } + /// Calisma dizininden yukari dogru cikarak depodaki configs/seeds klasorunu arar. private static string? FindRepositorySeedsPath() { diff --git a/configs/seeds/host/crud/.gitkeep b/configs/seeds/host/crud/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/configs/seeds/host/custom/.gitkeep b/configs/seeds/host/custom/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/configs/seeds/host/postgres/execute/.gitkeep b/configs/seeds/host/postgres/execute/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/configs/seeds/PostgresData/HostData/ExecuteData/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql b/configs/seeds/host/postgres/execute/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql similarity index 100% rename from configs/seeds/PostgresData/HostData/ExecuteData/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql rename to configs/seeds/host/postgres/execute/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql diff --git a/configs/seeds/host/postgres/object/.gitkeep b/configs/seeds/host/postgres/object/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/configs/seeds/PostgresData/HostData/ObjectData/Adm_T_DatabaseBackupAll.sql b/configs/seeds/host/postgres/object/Adm_T_DatabaseBackupAll.sql similarity index 100% rename from configs/seeds/PostgresData/HostData/ObjectData/Adm_T_DatabaseBackupAll.sql rename to configs/seeds/host/postgres/object/Adm_T_DatabaseBackupAll.sql diff --git a/configs/seeds/PostgresData/HostData/ObjectData/Adm_T_DatabaseBackupFilesDeleteAll.sql b/configs/seeds/host/postgres/object/Adm_T_DatabaseBackupFilesDeleteAll.sql similarity index 100% rename from configs/seeds/PostgresData/HostData/ObjectData/Adm_T_DatabaseBackupFilesDeleteAll.sql rename to configs/seeds/host/postgres/object/Adm_T_DatabaseBackupFilesDeleteAll.sql diff --git a/configs/seeds/PostgresData/HostData/ObjectData/Sas_H_BackgroundWorker_JobFlow.sql b/configs/seeds/host/postgres/object/Sas_H_BackgroundWorker_JobFlow.sql similarity index 100% rename from configs/seeds/PostgresData/HostData/ObjectData/Sas_H_BackgroundWorker_JobFlow.sql rename to configs/seeds/host/postgres/object/Sas_H_BackgroundWorker_JobFlow.sql diff --git a/configs/seeds/PostgresData/HostData/ObjectData/Sas_H_ListFormFieldsDictionaryJson.sql b/configs/seeds/host/postgres/object/Sas_H_ListFormFieldsDictionaryJson.sql similarity index 100% rename from configs/seeds/PostgresData/HostData/ObjectData/Sas_H_ListFormFieldsDictionaryJson.sql rename to configs/seeds/host/postgres/object/Sas_H_ListFormFieldsDictionaryJson.sql diff --git a/configs/seeds/PostgresData/HostData/ObjectData/Sas_H_OrderItem_ByTenantId.sql b/configs/seeds/host/postgres/object/Sas_H_OrderItem_ByTenantId.sql similarity index 100% rename from configs/seeds/PostgresData/HostData/ObjectData/Sas_H_OrderItem_ByTenantId.sql rename to configs/seeds/host/postgres/object/Sas_H_OrderItem_ByTenantId.sql diff --git a/configs/seeds/host/sql/execute/.gitkeep b/configs/seeds/host/sql/execute/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/configs/seeds/SqlData/HostData/ExecuteData/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql b/configs/seeds/host/sql/execute/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql similarity index 100% rename from configs/seeds/SqlData/HostData/ExecuteData/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql rename to configs/seeds/host/sql/execute/Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns.sql diff --git a/configs/seeds/host/sql/object/.gitkeep b/configs/seeds/host/sql/object/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/configs/seeds/SqlData/HostData/ObjectData/Adm_T_DatabaseBackupAll.sql b/configs/seeds/host/sql/object/Adm_T_DatabaseBackupAll.sql similarity index 100% rename from configs/seeds/SqlData/HostData/ObjectData/Adm_T_DatabaseBackupAll.sql rename to configs/seeds/host/sql/object/Adm_T_DatabaseBackupAll.sql diff --git a/configs/seeds/SqlData/HostData/ObjectData/Adm_T_DatabaseBackupFilesDeleteAll.sql b/configs/seeds/host/sql/object/Adm_T_DatabaseBackupFilesDeleteAll.sql similarity index 100% rename from configs/seeds/SqlData/HostData/ObjectData/Adm_T_DatabaseBackupFilesDeleteAll.sql rename to configs/seeds/host/sql/object/Adm_T_DatabaseBackupFilesDeleteAll.sql diff --git a/configs/seeds/SqlData/HostData/ObjectData/Sas_H_BackgroundWorker_JobFlow.sql b/configs/seeds/host/sql/object/Sas_H_BackgroundWorker_JobFlow.sql similarity index 100% rename from configs/seeds/SqlData/HostData/ObjectData/Sas_H_BackgroundWorker_JobFlow.sql rename to configs/seeds/host/sql/object/Sas_H_BackgroundWorker_JobFlow.sql diff --git a/configs/seeds/SqlData/HostData/ObjectData/Sas_H_ListFormFieldsDictionaryJson.sql b/configs/seeds/host/sql/object/Sas_H_ListFormFieldsDictionaryJson.sql similarity index 100% rename from configs/seeds/SqlData/HostData/ObjectData/Sas_H_ListFormFieldsDictionaryJson.sql rename to configs/seeds/host/sql/object/Sas_H_ListFormFieldsDictionaryJson.sql diff --git a/configs/seeds/SqlData/HostData/ObjectData/Sas_H_OrderItem_ByTenantId.sql b/configs/seeds/host/sql/object/Sas_H_OrderItem_ByTenantId.sql similarity index 100% rename from configs/seeds/SqlData/HostData/ObjectData/Sas_H_OrderItem_ByTenantId.sql rename to configs/seeds/host/sql/object/Sas_H_OrderItem_ByTenantId.sql diff --git a/configs/seeds/host/wizard/.gitkeep b/configs/seeds/host/wizard/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/configs/seeds/tenants/.gitkeep b/configs/seeds/tenants/.gitkeep new file mode 100644 index 00000000..e69de29b