diff --git a/.github/instructions/lowcode.instructions.md b/.github/instructions/lowcode.instructions.md index 1cd9bb09..2b1438a5 100644 --- a/.github/instructions/lowcode.instructions.md +++ b/.github/instructions/lowcode.instructions.md @@ -3427,6 +3427,7 @@ kapalıyken dosya yalnızca seed sırasında okunur, hiç yazılmaz. | --- | --- | | `ListFormCode` | Verinin ait olduğu ekran; dosya adıyla aynı olmalı. Boşsa dosya adı kullanılır | | `KeyFieldName` | Satırların eşleştiği anahtar alan; boşsa `ListForm.KeyFieldName` | +| `Order` | Uygulama sırası; küçük olan önce uygulanır (yabancı anahtarlı tablolarda önce tanım dosyası). Yoksa `0`, eşitlikte dosya adına göre sıralanır | | `Rows` | Ekranın select alanlarından oluşan satırlar. Enum'lar **sayı** olarak yazılır (SQL kolonu ne ise o); dil anahtarları `::` öneki olmadan yazılır | Kurallar: diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ListFormSeedDataSynchronizer.cs b/api/src/Sozsoft.Platform.Application/ListForms/ListFormSeedDataSynchronizer.cs index 32c48493..49640604 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ListFormSeedDataSynchronizer.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ListFormSeedDataSynchronizer.cs @@ -138,12 +138,11 @@ public class ListFormSeedDataSynchronizer( RequireGroupCount = false, }); - await WriteSeedFileAsync(filePath, new ListFormSeedDataFileDto - { - ListFormCode = listForm.ListFormCode, - KeyFieldName = listForm.KeyFieldName, - Rows = ToRows((object)result?.Data) - }); + // Uygulama sirasi dosyanin kendi bilgisidir; listeden uretilemez, var olan degeri korunur. + var seedFile = await ReadSeedFileAsync(filePath, listForm); + seedFile.Rows = ToRows((object)result?.Data); + + await WriteSeedFileAsync(filePath, seedFile); } /// diff --git a/api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs b/api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs index 4793e371..d9eb0165 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs @@ -3140,6 +3140,10 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency Description = $"{listFormName}.Description", SelectCommandType = SelectCommandTypeEnum.Table, SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.SkillType)), + SeedFilePath = SeedPathResolver.GetDataFilePath(listFormName), + SeedSyncInsert = false, + SeedSyncUpdate = false, + SeedSyncDelete = false, KeyFieldName = "Id", KeyFieldDbSourceType = DbType.String, DefaultFilter = DefaultFilterJson, @@ -3257,6 +3261,10 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency Description = $"{listFormName}.Description", SelectCommandType = SelectCommandTypeEnum.Table, SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.SkillLevel)), + SeedFilePath = SeedPathResolver.GetDataFilePath(listFormName), + SeedSyncInsert = false, + SeedSyncUpdate = false, + SeedSyncDelete = false, KeyFieldName = "Id", KeyFieldDbSourceType = DbType.String, DefaultFilter = DefaultFilterJson, @@ -3410,6 +3418,10 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency Description = $"{listFormName}.Description", SelectCommandType = SelectCommandTypeEnum.Table, SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.Skill)), + SeedFilePath = SeedPathResolver.GetDataFilePath(listFormName), + SeedSyncInsert = false, + SeedSyncUpdate = false, + SeedSyncDelete = false, KeyFieldName = "Id", KeyFieldDbSourceType = DbType.String, DefaultFilter = DefaultFilterJson, diff --git a/api/src/Sozsoft.Platform.Domain/Data/ListFormSeedDataApplier.cs b/api/src/Sozsoft.Platform.Domain/Data/ListFormSeedDataApplier.cs index d38ac8dd..0586530c 100644 --- a/api/src/Sozsoft.Platform.Domain/Data/ListFormSeedDataApplier.cs +++ b/api/src/Sozsoft.Platform.Domain/Data/ListFormSeedDataApplier.cs @@ -61,7 +61,7 @@ public class ListFormSeedDataApplier( return; } - var jsonFiles = Directory.GetFiles(dataPath, "*.json").OrderBy(Path.GetFileName).ToArray(); + var jsonFiles = OrderFiles(Directory.GetFiles(dataPath, "*.json")); if (jsonFiles.Length == 0) { logger.LogInformation("No JSON files found in Seeds/{Scope}/data directory, skipping ListFormSeedDataApplier.", scopeFolderName); @@ -85,6 +85,37 @@ public class ListFormSeedDataApplier( logger.LogInformation("ListFormSeedDataApplier completed for {Scope}.", scopeFolderName); } + /// + /// Dosyalari Order alanina, esitlikte dosya adina gore siralar. Yabanci anahtarla + /// bagli tablolarda referans verilen tanim once uygulanmalidir; okunamayan dosya sona kalir + /// ve hatasi kendi isleminde raporlanir. + /// + private static string[] OrderFiles(string[] filePaths) + { + return [.. filePaths + .Select(filePath => (FilePath: filePath, Order: ReadOrder(filePath))) + .OrderBy(a => a.Order) + .ThenBy(a => Path.GetFileName(a.FilePath)) + .Select(a => a.FilePath)]; + } + + private static int ReadOrder(string filePath) + { + try + { + using var document = JsonDocument.Parse(File.ReadAllText(filePath)); + + return document.RootElement.TryGetProperty(nameof(ListFormSeedDataFileDto.Order), out var order) + && order.TryGetInt32(out var value) + ? value + : 0; + } + catch (Exception) + { + return int.MaxValue; + } + } + private async Task ApplyFileAsync(string filePath) { var fileName = Path.GetFileName(filePath); diff --git a/api/src/Sozsoft.Platform.Domain/Data/ListFormSeedDataFile.cs b/api/src/Sozsoft.Platform.Domain/Data/ListFormSeedDataFile.cs index 4e3dbadc..0e5acd75 100644 --- a/api/src/Sozsoft.Platform.Domain/Data/ListFormSeedDataFile.cs +++ b/api/src/Sozsoft.Platform.Domain/Data/ListFormSeedDataFile.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; @@ -25,6 +25,13 @@ public class ListFormSeedDataFileDto /// Dosyanin en son yazildigi an (UTC) — yalnizca bilgi amaclidir. public DateTime GeneratedAt { get; set; } + /// + /// Uygulama sirasi; kucuk olan once uygulanir. Yabanci anahtarla bagli tablolarda + /// (once tanim, sonra ona referans veren satirlar) kullanilir. Ayni degerde olanlar + /// dosya adina gore siralanir. + /// + public int Order { get; set; } + /// Ekranin select alanlarindan olusan satirlar; sira dosyadaki sirayi korur. public List> Rows { get; set; } = []; diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantData.json b/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantData.json index 6fd0679b..4bf89cac 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantData.json +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantData.json @@ -391,211 +391,6 @@ } } ], - "SkillTypes": [ - { - "Name": "Diller" - }, - { - "Name": "Soft Skills" - }, - { - "Name": "Technical Skills" - } - ], - "Skills": [ - { - "SkillTypeName": "Diller", - "Name": "Spanish" - }, - { - "SkillTypeName": "Diller", - "Name": "Fransızca" - }, - { - "SkillTypeName": "Diller", - "Name": "English" - }, - { - "SkillTypeName": "Diller", - "Name": "German" - }, - { - "SkillTypeName": "Diller", - "Name": "Filipino" - }, - { - "SkillTypeName": "Diller", - "Name": "Arabic" - }, - { - "SkillTypeName": "Diller", - "Name": "Bengali" - }, - { - "SkillTypeName": "Diller", - "Name": "Mandarin Chinese" - }, - { - "SkillTypeName": "Diller", - "Name": "Wu Chinese" - }, - { - "SkillTypeName": "Diller", - "Name": "Hindi" - }, - { - "SkillTypeName": "Diller", - "Name": "Russian" - }, - { - "SkillTypeName": "Diller", - "Name": "Portuguese" - }, - { - "SkillTypeName": "Diller", - "Name": "Indonesian" - }, - { - "SkillTypeName": "Diller", - "Name": "Urdu" - }, - { - "SkillTypeName": "Diller", - "Name": "Japonca" - }, - { - "SkillTypeName": "Diller", - "Name": "Punjabi" - }, - { - "SkillTypeName": "Diller", - "Name": "Javanese" - }, - { - "SkillTypeName": "Diller", - "Name": "Telugu" - }, - { - "SkillTypeName": "Diller", - "Name": "Turkish" - }, - { - "SkillTypeName": "Diller", - "Name": "Korean" - }, - { - "SkillTypeName": "Diller", - "Name": "Marathi" - }, - { - "SkillTypeName": "Soft Skills", - "Name": "Adaptability" - }, - { - "SkillTypeName": "Soft Skills", - "Name": "Critical Thinking" - }, - { - "SkillTypeName": "Soft Skills", - "Name": "İletişim" - }, - { - "SkillTypeName": "Technical Skills", - "Name": "Torna Operatörü" - }, - { - "SkillTypeName": "Technical Skills", - "Name": "Mekanik" - }, - { - "SkillTypeName": "Technical Skills", - "Name": "Kompresör Teknisyeni" - }, - { - "SkillTypeName": "Technical Skills", - "Name": "Elektrikçi" - }, - { - "SkillTypeName": "Technical Skills", - "Name": "PLC Teknisyeni" - }, - { - "SkillTypeName": "Technical Skills", - "Name": "Robot Teknisyeni" - }, - { - "SkillTypeName": "Technical Skills", - "Name": "Kaynak Uzmanı" - } - ], - "SkillLevels": [ - { - "SkillTypeName": "Diller", - "Name": "C2", - "Progress": 100, - "IsDefault": false - }, - { - "SkillTypeName": "Diller", - "Name": "C1", - "Progress": 85, - "IsDefault": false - }, - { - "SkillTypeName": "Diller", - "Name": "B2", - "Progress": 75, - "IsDefault": false - }, - { - "SkillTypeName": "Diller", - "Name": "B1", - "Progress": 60, - "IsDefault": false - }, - { - "SkillTypeName": "Diller", - "Name": "A2", - "Progress": 40, - "IsDefault": false - }, - { - "SkillTypeName": "Diller", - "Name": "A1", - "Progress": 10, - "IsDefault": true - }, - { - "SkillTypeName": "Soft Skills", - "Name": "Expert", - "Progress": 100, - "IsDefault": false - }, - { - "SkillTypeName": "Soft Skills", - "Name": "Advanced", - "Progress": 80, - "IsDefault": false - }, - { - "SkillTypeName": "Soft Skills", - "Name": "Intermediate", - "Progress": 50, - "IsDefault": false - }, - { - "SkillTypeName": "Soft Skills", - "Name": "Elementary", - "Progress": 25, - "IsDefault": false - }, - { - "SkillTypeName": "Soft Skills", - "Name": "Beginner", - "Progress": 15, - "IsDefault": true - } - ], "UomCategories": [ { "Name": "Adet" diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantDataSeeder.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantDataSeeder.cs index 190914d7..96f7ed21 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantDataSeeder.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantDataSeeder.cs @@ -27,9 +27,6 @@ public class TenantSeederDto public List WorkHours { get; set; } public List UomCategories { get; set; } public List Uoms { get; set; } - public List SkillTypes { get; set; } - public List Skills { get; set; } - public List SkillLevels { get; set; } public List Departments { get; set; } public List JobPositions { get; set; } @@ -236,25 +233,6 @@ public class UomSeedDto public string UomCategoryName { get; set; } } -public class SkillTypeSeedDto -{ - public string Name { get; set; } -} - -public class SkillSeedDto -{ - public string Name { get; set; } - public string SkillTypeName { get; set; } -} - -public class SkillLevelSeedDto -{ - public string Name { get; set; } - public int Progress { get; set; } - public bool IsDefault { get; set; } - public string SkillTypeName { get; set; } -} - public class ForumCategorySeedDto { public string Name { get; set; } @@ -384,9 +362,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency private readonly IRepository _aboutRepository; private readonly IRepository _servicesRepository; private readonly IRepository _contactRepository; - private readonly IRepository _skillTypeRepository; - private readonly IRepository _skillRepository; - private readonly IRepository _skillLevelRepository; private readonly IRepository _uomCategoryRepository; private readonly IRepository _uomRepository; private readonly IRepository _forumCategoryRepository; @@ -416,9 +391,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency IRepository branchRepository, IRepository uomCategoryRepository, IRepository uomRepository, - IRepository skillTypeRepository, - IRepository skillRepository, - IRepository skillLevelRepository, IRepository reportCategoriesRepository, IRepository reportTemplatesRepository, IRepository homeRepository, @@ -450,9 +422,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency _branchRepository = branchRepository; _uomCategoryRepository = uomCategoryRepository; _uomRepository = uomRepository; - _skillTypeRepository = skillTypeRepository; - _skillRepository = skillRepository; - _skillLevelRepository = skillLevelRepository; _reportCategoriesRepository = reportCategoriesRepository; _reportTemplatesRepository = reportTemplatesRepository; _homeRepository = homeRepository; @@ -525,54 +494,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency } } - foreach (var item in items.SkillTypes) - { - var exists = await _skillTypeRepository.AnyAsync(x => x.Name == item.Name); - - if (!exists) - { - await _skillTypeRepository.InsertAsync(new SkillType(item.Name) { Name = item.Name }, autoSave: true); - } - } - - foreach (var item in items.Skills) - { - var exists = await _skillRepository.AnyAsync(x => x.Name == item.Name); - - if (!exists) - { - var skillType = await _skillTypeRepository.FirstOrDefaultAsync(x => x.Name == item.SkillTypeName); - if (skillType != null) - { - await _skillRepository.InsertAsync(new Skill(item.Name) - { - Name = item.Name, - SkillTypeId = skillType.Id - }); - } - } - } - - foreach (var item in items.SkillLevels) - { - var exists = await _skillLevelRepository.AnyAsync(x => x.Name == item.Name); - - if (!exists) - { - var skillType = await _skillTypeRepository.FirstOrDefaultAsync(x => x.Name == item.SkillTypeName); - if (skillType != null) - { - await _skillLevelRepository.InsertAsync(new SkillLevel(item.Name) - { - Name = item.Name, - Progress = item.Progress, - IsDefault = item.IsDefault, - SkillTypeId = skillType.Id, - }); - } - } - } - foreach (var item in items.ForumCategories) { var exists = await _forumCategoryRepository.AnyAsync(x => x.Name == item.Name); diff --git a/configs/seeds/host/data/App.Definitions.Skill.json b/configs/seeds/host/data/App.Definitions.Skill.json new file mode 100644 index 00000000..f9d44c43 --- /dev/null +++ b/configs/seeds/host/data/App.Definitions.Skill.json @@ -0,0 +1,163 @@ +{ + "ListFormCode": "App.Definitions.Skill", + "KeyFieldName": "Id", + "GeneratedAt": "2026-09-04T00:00:00Z", + "Order": 20, + "Rows": [ + { + "Id": "Spanish", + "Name": "Spanish", + "SkillTypeId": "Diller" + }, + { + "Id": "Fransızca", + "Name": "Fransızca", + "SkillTypeId": "Diller" + }, + { + "Id": "English", + "Name": "English", + "SkillTypeId": "Diller" + }, + { + "Id": "German", + "Name": "German", + "SkillTypeId": "Diller" + }, + { + "Id": "Filipino", + "Name": "Filipino", + "SkillTypeId": "Diller" + }, + { + "Id": "Arabic", + "Name": "Arabic", + "SkillTypeId": "Diller" + }, + { + "Id": "Bengali", + "Name": "Bengali", + "SkillTypeId": "Diller" + }, + { + "Id": "Mandarin Chinese", + "Name": "Mandarin Chinese", + "SkillTypeId": "Diller" + }, + { + "Id": "Wu Chinese", + "Name": "Wu Chinese", + "SkillTypeId": "Diller" + }, + { + "Id": "Hindi", + "Name": "Hindi", + "SkillTypeId": "Diller" + }, + { + "Id": "Russian", + "Name": "Russian", + "SkillTypeId": "Diller" + }, + { + "Id": "Portuguese", + "Name": "Portuguese", + "SkillTypeId": "Diller" + }, + { + "Id": "Indonesian", + "Name": "Indonesian", + "SkillTypeId": "Diller" + }, + { + "Id": "Urdu", + "Name": "Urdu", + "SkillTypeId": "Diller" + }, + { + "Id": "Japonca", + "Name": "Japonca", + "SkillTypeId": "Diller" + }, + { + "Id": "Punjabi", + "Name": "Punjabi", + "SkillTypeId": "Diller" + }, + { + "Id": "Javanese", + "Name": "Javanese", + "SkillTypeId": "Diller" + }, + { + "Id": "Telugu", + "Name": "Telugu", + "SkillTypeId": "Diller" + }, + { + "Id": "Turkish", + "Name": "Turkish", + "SkillTypeId": "Diller" + }, + { + "Id": "Korean", + "Name": "Korean", + "SkillTypeId": "Diller" + }, + { + "Id": "Marathi", + "Name": "Marathi", + "SkillTypeId": "Diller" + }, + { + "Id": "Adaptability", + "Name": "Adaptability", + "SkillTypeId": "Soft Skills" + }, + { + "Id": "Critical Thinking", + "Name": "Critical Thinking", + "SkillTypeId": "Soft Skills" + }, + { + "Id": "İletişim", + "Name": "İletişim", + "SkillTypeId": "Soft Skills" + }, + { + "Id": "Torna Operatörü", + "Name": "Torna Operatörü", + "SkillTypeId": "Technical Skills" + }, + { + "Id": "Mekanik", + "Name": "Mekanik", + "SkillTypeId": "Technical Skills" + }, + { + "Id": "Kompresör Teknisyeni", + "Name": "Kompresör Teknisyeni", + "SkillTypeId": "Technical Skills" + }, + { + "Id": "Elektrikçi", + "Name": "Elektrikçi", + "SkillTypeId": "Technical Skills" + }, + { + "Id": "PLC Teknisyeni", + "Name": "PLC Teknisyeni", + "SkillTypeId": "Technical Skills" + }, + { + "Id": "Robot Teknisyeni", + "Name": "Robot Teknisyeni", + "SkillTypeId": "Technical Skills" + }, + { + "Id": "Kaynak Uzmanı", + "Name": "Kaynak Uzmanı", + "SkillTypeId": "Technical Skills" + } + ] +} diff --git a/configs/seeds/host/data/App.Definitions.SkillLevel.json b/configs/seeds/host/data/App.Definitions.SkillLevel.json new file mode 100644 index 00000000..16265775 --- /dev/null +++ b/configs/seeds/host/data/App.Definitions.SkillLevel.json @@ -0,0 +1,85 @@ +{ + "ListFormCode": "App.Definitions.SkillLevel", + "KeyFieldName": "Id", + "GeneratedAt": "2026-09-04T00:00:00Z", + "Order": 20, + "Rows": [ + { + "Id": "C2", + "Name": "C2", + "Progress": 100, + "IsDefault": false, + "SkillTypeId": "Diller" + }, + { + "Id": "C1", + "Name": "C1", + "Progress": 85, + "IsDefault": false, + "SkillTypeId": "Diller" + }, + { + "Id": "B2", + "Name": "B2", + "Progress": 75, + "IsDefault": false, + "SkillTypeId": "Diller" + }, + { + "Id": "B1", + "Name": "B1", + "Progress": 60, + "IsDefault": false, + "SkillTypeId": "Diller" + }, + { + "Id": "A2", + "Name": "A2", + "Progress": 40, + "IsDefault": false, + "SkillTypeId": "Diller" + }, + { + "Id": "A1", + "Name": "A1", + "Progress": 10, + "IsDefault": true, + "SkillTypeId": "Diller" + }, + { + "Id": "Expert", + "Name": "Expert", + "Progress": 100, + "IsDefault": false, + "SkillTypeId": "Soft Skills" + }, + { + "Id": "Advanced", + "Name": "Advanced", + "Progress": 80, + "IsDefault": false, + "SkillTypeId": "Soft Skills" + }, + { + "Id": "Intermediate", + "Name": "Intermediate", + "Progress": 50, + "IsDefault": false, + "SkillTypeId": "Soft Skills" + }, + { + "Id": "Elementary", + "Name": "Elementary", + "Progress": 25, + "IsDefault": false, + "SkillTypeId": "Soft Skills" + }, + { + "Id": "Beginner", + "Name": "Beginner", + "Progress": 15, + "IsDefault": true, + "SkillTypeId": "Soft Skills" + } + ] +} diff --git a/configs/seeds/host/data/App.Definitions.SkillType.json b/configs/seeds/host/data/App.Definitions.SkillType.json new file mode 100644 index 00000000..048606b4 --- /dev/null +++ b/configs/seeds/host/data/App.Definitions.SkillType.json @@ -0,0 +1,20 @@ +{ + "ListFormCode": "App.Definitions.SkillType", + "KeyFieldName": "Id", + "GeneratedAt": "2026-09-04T00:00:00Z", + "Order": 10, + "Rows": [ + { + "Id": "Diller", + "Name": "Diller" + }, + { + "Id": "Soft Skills", + "Name": "Soft Skills" + }, + { + "Id": "Technical Skills", + "Name": "Technical Skills" + } + ] +}