From 8be61336612ce64cfdff45a36da1246335249f9f Mon Sep 17 00:00:00 2001 From: alireza Date: Tue, 9 Jun 2026 01:31:37 +0330 Subject: [PATCH] feat: add DataSeeder for reference/test data and auto-migration on startup --- Complex.EndPoint/Program.cs | 16 + Complex.Infrastructure/DataSeeder.cs | 510 +++++++++++++++++++++++++++ 2 files changed, 526 insertions(+) create mode 100644 Complex.Infrastructure/DataSeeder.cs diff --git a/Complex.EndPoint/Program.cs b/Complex.EndPoint/Program.cs index e55b8ca..a8dea95 100644 --- a/Complex.EndPoint/Program.cs +++ b/Complex.EndPoint/Program.cs @@ -19,6 +19,9 @@ using Swashbuckle.AspNetCore.SwaggerGen; using System.Reflection; using System.Text; using WebApi.Bugeto.Models.Services.Validator; +using Complex.Application.Services.TransactionServices; +using Complex.Application.Services.Announcement; +using Complex.Application.Services.Dashboard; var builder = WebApplication.CreateBuilder(args); builder.Logging.ClearProviders(); @@ -40,6 +43,9 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); //eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiIqQCFJVE15QXpNX19fSVRPeGtETSIsIk5hbWUiOiIqQCE4S18xXzFfRm1kcllYWV8xXzFfIiwiRmFtaWx5IjoiKkAhKkAhQWpiWFlfMV8xX011ZHJZSExfMV8xXyIsIm5iZiI6MTcwNjg4ODQyOCwiZXhwIjoxNzA5NDgwNDI4LCJpc3MiOiJuYWJha3NvZnQuaXIiLCJhdWQiOiJDb21wbGV4In0.Hz7fF-bRW3KouPOGgc0p5UVCMQmKkroKzGLdmZeXZeg @@ -170,6 +176,16 @@ builder.Services.AddSwaggerGen(c => var app = builder.Build(); + +// Apply pending migrations automatically on startup +using (var scope = app.Services.CreateScope()) +{ + var dbContext = scope.ServiceProvider.GetRequiredService(); + dbContext.Database.Migrate(); + // Seed essential reference data and test data + await DataSeeder.SeedAsync(dbContext); +} + app.UseExceptionHandler(c => c.Run(async context => { var exception = context.Features diff --git a/Complex.Infrastructure/DataSeeder.cs b/Complex.Infrastructure/DataSeeder.cs new file mode 100644 index 0000000..c973533 --- /dev/null +++ b/Complex.Infrastructure/DataSeeder.cs @@ -0,0 +1,510 @@ +using Complex.Domain.Entities; +using Microsoft.EntityFrameworkCore; + +namespace Complex.Infrastructure +{ + public static class DataSeeder + { + public static async Task SeedAsync(ComplexDBContext context) + { + // Only seed if the database is empty (no provinces means fresh database) + if (await context.Set().AnyAsync()) + return; + + // ============================================================ + // 1. PROVINCES & CITIES (Reference Data) + // ============================================================ + var provinces = GetProvinces(); + context.Set().AddRange(provinces); + await context.SaveChangesAsync(); + + // ============================================================ + // 2. TRANSACTION TYPES (Reference Data) + // ============================================================ + var transactionTypes = new List + { + new() { Id = 1, Title = "درآمد" }, // Income + new() { Id = 2, Title = "مخارج" }, // Expense + }; + context.Set().AddRange(transactionTypes); + await context.SaveChangesAsync(); + + // ============================================================ + // 3. INCOME/COST TITLES (Reference Data) + // ============================================================ + var incomeCostTitles = new List + { + new() { Id = 1, Title = "شارژ ماهیانه", TransactionTypeId = 1 }, + new() { Id = 2, Title = "هزینه آب", TransactionTypeId = 2 }, + new() { Id = 3, Title = "هزینه برق", TransactionTypeId = 2 }, + new() { Id = 4, Title = "هزینه گاز", TransactionTypeId = 2 }, + new() { Id = 5, Title = "هزینه نظافت", TransactionTypeId = 2 }, + new() { Id = 6, Title = "هزینه تعمیرات", TransactionTypeId = 2 }, + new() { Id = 7, Title = "هزینه آسانسور", TransactionTypeId = 2 }, + new() { Id = 8, Title = "پارکینگ", TransactionTypeId = 1 }, + new() { Id = 9, Title = "جریمه", TransactionTypeId = 1 }, + new() { Id = 10, Title = "هزینه اینترنت", TransactionTypeId = 2 }, + new() { Id = 11, Title = "هزینه نگهبانی", TransactionTypeId = 2 }, + new() { Id = 12, Title = "هزینه باغبانی", TransactionTypeId = 2 }, + }; + context.Set().AddRange(incomeCostTitles); + await context.SaveChangesAsync(); + + // ============================================================ + // 4. UNIT STATES (Reference Data) + // ============================================================ + var unitStates = new List + { + new() { Id = 1, Title = "ساکن دارد", Icon = "home" }, + new() { Id = 2, Title = "خالی", Icon = "door-open" }, + new() { Id = 3, Title = "بازسازی", Icon = "hammer" }, + new() { Id = 4, Title = "اجاره داده شده", Icon = "key" }, + new() { Id = 5, Title = "فروخته شده", Icon = "handshake" }, + }; + context.Set().AddRange(unitStates); + await context.SaveChangesAsync(); + + // ============================================================ + // 5. PERSONS (Test Data) + // ============================================================ + var persons = new List + { + new() { Id = "09120000001", FirstName = "علی", LastName = "مدیر", Gender = 1, IsActive = true }, + new() { Id = "09120000002", FirstName = "رضا", LastName = "ساکن", Gender = 1, IsActive = true }, + new() { Id = "09120000003", FirstName = "مریم", LastName = "ساکنی", Gender = 2, IsActive = true }, + new() { Id = "09120000004", FirstName = "مدیر", LastName = "سیستم", Gender = 1, IsActive = true }, + new() { Id = "09120000005", FirstName = "احمد", LastName = "احمدی", Gender = 1, IsActive = true }, + new() { Id = "09120000006", FirstName = "سارا", LastName = "محمدی", Gender = 2, IsActive = true }, + new() { Id = "09120000007", FirstName = "حسین", LastName = "حسینی", Gender = 1, IsActive = true }, + new() { Id = "09120000008", FirstName = "زهرا", LastName = "رضایی", Gender = 2, IsActive = true }, + new() { Id = "09120000009", FirstName = "محمد", LastName = "محمدیان", Gender = 1, IsActive = true }, + new() { Id = "09120000010", FirstName = "فاطمه", LastName = "کریمی", Gender = 2, IsActive = true }, + new() { Id = "09120000011", FirstName = "امیر", LastName = "امیری", Gender = 1, IsActive = true }, + new() { Id = "09120000012", FirstName = "نرگس", LastName = "نرگسی", Gender = 2, IsActive = true }, + }; + context.Set().AddRange(persons); + await context.SaveChangesAsync(); + + // ============================================================ + // 6. COMPLEX ENTITIES (Test Data) + // ============================================================ + var complexId1 = Guid.Parse("A1B2C3D4-E5F6-7890-ABCD-EF1234567890"); + var complexId2 = Guid.Parse("B2C3D4E5-F6A7-8901-BCDE-F12345678901"); + + var complexes = new List + { + new() + { + Id = complexId1, + Title = "مجتمع بهاران", + Address = "تهران، خیابان ولیعصر، نبش کوچه بهار", + CityId = 1, // Tehran + AreaMeter = 2000, + YardMeter = 500, + ElevatorCount = 2, + WarehouseCount = 10, + YearMake = 1398, + Description = "مجتمع مسکونی 10 واحده با امکانات کامل" + }, + new() + { + Id = complexId2, + Title = "مجتمع ساحل", + Address = "اصفهان، خیابان چهارباغ، روبروی پارک ساحل", + CityId = 3, // Isfahan + AreaMeter = 1500, + YardMeter = 300, + ElevatorCount = 1, + WarehouseCount = 6, + YearMake = 1400, + Description = "مجتمع مسکونی 6 واحده" + }, + }; + context.Set().AddRange(complexes); + await context.SaveChangesAsync(); + + // ============================================================ + // 7. COMPLEX MANAGERS (Test Data) + // ============================================================ + var complexManagers = new List + { + new() + { + ComplexId = complexId1, + ManagerMobileNumberId = "09120000001", // علی مدیر + StartDate = "1402/01/01", + EndDate = "1405/12/29" + }, + new() + { + ComplexId = complexId2, + ManagerMobileNumberId = "09120000004", // مدیر سیستم + StartDate = "1402/06/01", + EndDate = "1405/06/01" + }, + }; + context.Set().AddRange(complexManagers); + await context.SaveChangesAsync(); + + // ============================================================ + // 8. COMPLEX PERSONS (Test Data) + // ============================================================ + var complexPersons = new List + { + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000001" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000002" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000003" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000005" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000006" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000007" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000008" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000009" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000010" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000011" }, + new() { ComplexId = complexId1, PersonMobileNumberId = "09120000012" }, + new() { ComplexId = complexId2, PersonMobileNumberId = "09120000004" }, + new() { ComplexId = complexId2, PersonMobileNumberId = "09120000005" }, + new() { ComplexId = complexId2, PersonMobileNumberId = "09120000006" }, + new() { ComplexId = complexId2, PersonMobileNumberId = "09120000007" }, + }; + context.Set().AddRange(complexPersons); + await context.SaveChangesAsync(); + + // ============================================================ + // 9. UNITS (Test Data) + // ============================================================ + var unitIds = new List + { + Guid.Parse("11111111-1111-1111-1111-111111111101"), + Guid.Parse("11111111-1111-1111-1111-111111111102"), + Guid.Parse("11111111-1111-1111-1111-111111111103"), + Guid.Parse("11111111-1111-1111-1111-111111111104"), + Guid.Parse("11111111-1111-1111-1111-111111111105"), + Guid.Parse("11111111-1111-1111-1111-111111111106"), + Guid.Parse("11111111-1111-1111-1111-111111111107"), + Guid.Parse("11111111-1111-1111-1111-111111111108"), + Guid.Parse("11111111-1111-1111-1111-111111111109"), + Guid.Parse("11111111-1111-1111-1111-111111111110"), + Guid.Parse("22222222-2222-2222-2222-222222222201"), + Guid.Parse("22222222-2222-2222-2222-222222222202"), + Guid.Parse("22222222-2222-2222-2222-222222222203"), + Guid.Parse("22222222-2222-2222-2222-222222222204"), + Guid.Parse("22222222-2222-2222-2222-222222222205"), + Guid.Parse("22222222-2222-2222-2222-222222222206"), + }; + + var units = new List + { + // Complex 1 - 10 units + new() { Id = unitIds[0], ComplexId = complexId1, UnitName = "واحد 1", OwnerId = "09120000002", TenantId = null, IsActive = true, AreaMeter = 120, Floor = 1, StateId = 1, EmergencyTels = "09120000002" }, + new() { Id = unitIds[1], ComplexId = complexId1, UnitName = "واحد 2", OwnerId = "09120000003", TenantId = null, IsActive = true, AreaMeter = 100, Floor = 1, StateId = 1, EmergencyTels = "09120000003" }, + new() { Id = unitIds[2], ComplexId = complexId1, UnitName = "واحد 3", OwnerId = "09120000005", TenantId = "09120000006", IsActive = true, AreaMeter = 110, Floor = 2, StateId = 4, EmergencyTels = "09120000005,09120000006" }, + new() { Id = unitIds[3], ComplexId = complexId1, UnitName = "واحد 4", OwnerId = "09120000007", TenantId = null, IsActive = true, AreaMeter = 130, Floor = 2, StateId = 1, EmergencyTels = "09120000007" }, + new() { Id = unitIds[4], ComplexId = complexId1, UnitName = "واحد 5", OwnerId = null, TenantId = null, IsActive = true, AreaMeter = 90, Floor = 3, StateId = 2, EmergencyTels = "" }, + new() { Id = unitIds[5], ComplexId = complexId1, UnitName = "واحد 6", OwnerId = "09120000008", TenantId = null, IsActive = true, AreaMeter = 140, Floor = 3, StateId = 1, EmergencyTels = "09120000008" }, + new() { Id = unitIds[6], ComplexId = complexId1, UnitName = "واحد 7", OwnerId = "09120000009", TenantId = "09120000010", IsActive = true, AreaMeter = 95, Floor = 4, StateId = 4, EmergencyTels = "09120000009,09120000010" }, + new() { Id = unitIds[7], ComplexId = complexId1, UnitName = "واحد 8", OwnerId = "09120000011", TenantId = null, IsActive = true, AreaMeter = 115, Floor = 4, StateId = 1, EmergencyTels = "09120000011" }, + new() { Id = unitIds[8], ComplexId = complexId1, UnitName = "واحد 9", OwnerId = "09120000012", TenantId = null, IsActive = true, AreaMeter = 105, Floor = 5, StateId = 1, EmergencyTels = "09120000012" }, + new() { Id = unitIds[9], ComplexId = complexId1, UnitName = "واحد 10", OwnerId = null, TenantId = null, IsActive = false,AreaMeter = 80, Floor = 5, StateId = 3, EmergencyTels = "" }, + // Complex 2 - 6 units + new() { Id = unitIds[10], ComplexId = complexId2, UnitName = "واحد 1", OwnerId = "09120000005", TenantId = null, IsActive = true, AreaMeter = 110, Floor = 1, StateId = 1, EmergencyTels = "09120000005" }, + new() { Id = unitIds[11], ComplexId = complexId2, UnitName = "واحد 2", OwnerId = "09120000006", TenantId = null, IsActive = true, AreaMeter = 90, Floor = 1, StateId = 1, EmergencyTels = "09120000006" }, + new() { Id = unitIds[12], ComplexId = complexId2, UnitName = "واحد 3", OwnerId = "09120000007", TenantId = null, IsActive = true, AreaMeter = 120, Floor = 2, StateId = 1, EmergencyTels = "09120000007" }, + new() { Id = unitIds[13], ComplexId = complexId2, UnitName = "واحد 4", OwnerId = null, TenantId = null, IsActive = true, AreaMeter = 85, Floor = 2, StateId = 2, EmergencyTels = "" }, + new() { Id = unitIds[14], ComplexId = complexId2, UnitName = "واحد 5", OwnerId = "09120000004", TenantId = null, IsActive = true, AreaMeter = 100, Floor = 3, StateId = 1, EmergencyTels = "09120000004" }, + new() { Id = unitIds[15], ComplexId = complexId2, UnitName = "واحد 6", OwnerId = null, TenantId = null, IsActive = false,AreaMeter = 95, Floor = 3, StateId = 3, EmergencyTels = "" }, + }; + context.Set().AddRange(units); + await context.SaveChangesAsync(); + + // ============================================================ + // 10. COST CYCLES (Test Data) + // ============================================================ + var costCycleId1 = Guid.Parse("CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCC01"); + var costCycleId2 = Guid.Parse("CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCC02"); + + var costCycles = new List + { + new() + { + Id = costCycleId1, + ComplexId = complexId1, + Title = "شارژ فروردین 1404", + StartDate = new DateOnly(1404, 1, 1), + EndDate = new DateOnly(1404, 1, 31), + Amount = 500000, + EncouragementDay = 10, + EncouragementAmount = 450000, + IncomeCostTitleId = null, // شارژ ماهیانه + }, + new() + { + Id = costCycleId2, + ComplexId = complexId1, + Title = "هزینه نظافت فروردین 1404", + StartDate = new DateOnly(1404, 1, 1), + EndDate = new DateOnly(1404, 1, 31), + Amount = 200000, + EncouragementDay = 0, + EncouragementAmount = 0, + IncomeCostTitleId = 5, // هزینه نظافت + }, + }; + context.Set().AddRange(costCycles); + await context.SaveChangesAsync(); + + // Associate CostCycles with Units (many-to-many via CostCycleUnit) + // For costCycle1 - all units of complex1 + var complex1Units = units.Take(10).ToList(); + foreach (var unit in complex1Units) + { + // We need to add to the join table manually via the navigation property + var cycle1 = await context.Set().Include(c => c.Units).FirstAsync(c => c.Id == costCycleId1); + cycle1.Units.Add(unit); + } + // For costCycle2 - only units 1,2,3,4 of complex1 + var selectedUnits = units.Take(4).ToList(); + var cycle2 = await context.Set().Include(c => c.Units).FirstAsync(c => c.Id == costCycleId2); + foreach (var unit in selectedUnits) + { + cycle2.Units.Add(unit); + } + await context.SaveChangesAsync(); + + // ============================================================ + // 11. UNIT COSTS (Test Data) + // ============================================================ + var unitCosts = new List(); + long unitCostId = 1; + foreach (var unit in complex1Units) + { + unitCosts.Add(new UnitCost + { + Id = unitCostId++, + CostCycleId = costCycleId1, + UnitId = unit.Id, + Date = new DateOnly(1404, 1, 1), + TransactionId = null + }); + } + foreach (var unit in selectedUnits) + { + unitCosts.Add(new UnitCost + { + Id = unitCostId++, + CostCycleId = costCycleId2, + UnitId = unit.Id, + Date = new DateOnly(1404, 1, 1), + TransactionId = null + }); + } + context.Set().AddRange(unitCosts); + await context.SaveChangesAsync(); + + // ============================================================ + // 12. TRANSACTIONS (Test Data - some paid, some unpaid) + // ============================================================ + var transactions = new List + { + new() + { + Id = 1, + TransactionTitleId = null, // شارژ + TransactionPersianDate = "1404/01/15", + TransactionDate = new DateTime(2025, 4, 4), + Amount = 500000, + Description = "پرداخت شارژ فروردین - واحد 1", + CostCycleId = costCycleId1, + UnitId = unitIds[0], + UnitCostId = 1, // First UnitCost + ComplexId = complexId1, + PersonId = "09120000002", + FicheId = "FICHE-001" + }, + new() + { + Id = 2, + TransactionTitleId = null, + TransactionPersianDate = "1404/01/20", + TransactionDate = new DateTime(2025, 4, 9), + Amount = 500000, + Description = "پرداخت شارژ فروردین - واحد 2", + CostCycleId = costCycleId1, + UnitId = unitIds[1], + UnitCostId = 2, + ComplexId = complexId1, + PersonId = "09120000003", + FicheId = "FICHE-002" + }, + new() + { + Id = 3, + TransactionTitleId = 5, // هزینه نظافت + TransactionPersianDate = "1404/01/25", + TransactionDate = new DateTime(2025, 4, 14), + Amount = 200000, + Description = "پرداخت هزینه نظافت - واحد 1", + CostCycleId = costCycleId2, + UnitId = unitIds[0], + UnitCostId = 11, + ComplexId = complexId1, + PersonId = "09120000002", + FicheId = "FICHE-003" + }, + }; + context.Set().AddRange(transactions); + await context.SaveChangesAsync(); + + // Update UnitCosts to mark them as paid (link TransactionId) + var paidUnitCost1 = await context.Set().FindAsync(1L); + if (paidUnitCost1 != null) paidUnitCost1.TransactionId = 1; + + var paidUnitCost2 = await context.Set().FindAsync(2L); + if (paidUnitCost2 != null) paidUnitCost2.TransactionId = 2; + + var paidUnitCost11 = await context.Set().FindAsync(11L); + if (paidUnitCost11 != null) paidUnitCost11.TransactionId = 3; + + await context.SaveChangesAsync(); + + // ============================================================ + // 13. CHATS (Test Data) + // ============================================================ + var chats = new List + { + new() + { + ComplexId = complexId1, + PersonMobileNumber = "09120000002", + Body = "سلام. وقت بخیر. لطفاً در مورد شارژ ماه جاری راهنمایی بفرمایید.", + ChatTypeId = 1 + }, + new() + { + ComplexId = complexId1, + PersonMobileNumber = "09120000001", + Body = "سلام. شارژ فروردین ۵۰۰ هزار تومان است. مهلت پرداخت تا ۱۰ فروردین با تخفیف می‌باشد.", + ChatTypeId = 2 + }, + new() + { + ComplexId = complexId1, + PersonMobileNumber = "09120000005", + Body = "آسانسور طبقه ۳ مشکل دارد. لطفاً رسیدگی کنید.", + ChatTypeId = 1 + }, + }; + context.Set().AddRange(chats); + await context.SaveChangesAsync(); + + // ============================================================ + // 14. COMPLEX UNIT EVENTS (Test Data) + // ============================================================ + var events = new List + { + new() + { + UnitId = unitIds[0], + EventDate = "1404/01/05", + RegisterMobileNumber = "09120000002", + Body = "تعویض کنتور آب", + Description = "کنتور آب واحد ۱ تعویض شد" + }, + new() + { + UnitId = unitIds[2], + EventDate = "1404/01/10", + RegisterMobileNumber = "09120000005", + Body = "تعمیر شیرآلات", + Description = "شیرآلات آشپزخانه تعمیر شد" + }, + new() + { + ComplexId = null, + UnitId = null, + EventDate = "1404/01/01", + RegisterMobileNumber = "09120000001", + Body = "سال نو مبارک", + Description = "تبریک سال نو به تمام ساکنین مجتمع" + }, + }; + context.Set().AddRange(events); + await context.SaveChangesAsync(); + + // ============================================================ + // 15. POSTERS (Test Data) + // ============================================================ + var posters = new List + { + new() + { + RegisterMobileNumber = "09120000001", + IsActive = true, + ImagePath = "/images/posters/banner1.jpg" + }, + new() + { + RegisterMobileNumber = "09120000001", + IsActive = false, + ImagePath = "/images/posters/banner2.jpg" + }, + }; + context.Set().AddRange(posters); + await context.SaveChangesAsync(); + } + + private static List GetProvinces() + { + return new List + { + new() { ProvinceId = 1, ProvinceTitle = "آذربایجان شرقی", Cities = GetCities(1, "تبریز", "مراغه", "مرند", "میانه") }, + new() { ProvinceId = 2, ProvinceTitle = "آذربایجان غربی", Cities = GetCities(2, "ارومیه", "خوی", "میاندوآب", "سلماس") }, + new() { ProvinceId = 3, ProvinceTitle = "اردبیل", Cities = GetCities(3, "اردبیل", "پارس‌آباد", "مشگین‌شهر") }, + new() { ProvinceId = 4, ProvinceTitle = "اصفهان", Cities = GetCities(4, "اصفهان", "کاشان", "خمینی‌شهر", "نجف‌آباد", "شهرضا") }, + new() { ProvinceId = 5, ProvinceTitle = "البرز", Cities = GetCities(5, "کرج", "فردیس", "هشتگرد") }, + new() { ProvinceId = 6, ProvinceTitle = "ایلام", Cities = GetCities(6, "ایلام", "دهلران") }, + new() { ProvinceId = 7, ProvinceTitle = "بوشهر", Cities = GetCities(7, "بوشهر", "برازجان", "کنگان") }, + new() { ProvinceId = 8, ProvinceTitle = "تهران", Cities = GetCities(8, "تهران", "شهریار", "اسلامشهر", "رباط‌کریم", "ورامین") }, + new() { ProvinceId = 9, ProvinceTitle = "چهارمحال و بختیاری", Cities = GetCities(9, "شهرکرد", "بروجن") }, + new() { ProvinceId = 10, ProvinceTitle = "خراسان جنوبی", Cities = GetCities(10, "بیرجند", "قائن") }, + new() { ProvinceId = 11, ProvinceTitle = "خراسان رضوی", Cities = GetCities(11, "مشهد", "نیشابور", "سبزوار", "گناباد", "تربت‌حیدریه") }, + new() { ProvinceId = 12, ProvinceTitle = "خراسان شمالی", Cities = GetCities(12, "بجنورد", "شیروان") }, + new() { ProvinceId = 13, ProvinceTitle = "خوزستان", Cities = GetCities(13, "اهواز", "آبادان", "خرمشهر", "دزفول", "بندر ماهشهر") }, + new() { ProvinceId = 14, ProvinceTitle = "زنجان", Cities = GetCities(14, "زنجان", "ابهر") }, + new() { ProvinceId = 15, ProvinceTitle = "سمنان", Cities = GetCities(15, "سمنان", "شاهرود", "دامغان") }, + new() { ProvinceId = 16, ProvinceTitle = "سیستان و بلوچستان", Cities = GetCities(16, "زاهدان", "زابل", "چابهار", "ایرانشهر") }, + new() { ProvinceId = 17, ProvinceTitle = "فارس", Cities = GetCities(17, "شیراز", "مرودشت", "جهرم", "فسا", "کازرون") }, + new() { ProvinceId = 18, ProvinceTitle = "قزوین", Cities = GetCities(18, "قزوین", "الوند", "تاکستان") }, + new() { ProvinceId = 19, ProvinceTitle = "قم", Cities = GetCities(19, "قم") }, + new() { ProvinceId = 20, ProvinceTitle = "کردستان", Cities = GetCities(20, "سنندج", "سقز", "مریوان") }, + new() { ProvinceId = 21, ProvinceTitle = "کرمان", Cities = GetCities(21, "کرمان", "رفسنجان", "سیرجان", "زرند") }, + new() { ProvinceId = 22, ProvinceTitle = "کرمانشاه", Cities = GetCities(22, "کرمانشاه", "اسلام‌آباد غرب", "کنگاور") }, + new() { ProvinceId = 23, ProvinceTitle = "کهگیلویه و بویراحمد", Cities = GetCities(23, "یاسوج", "گچساران") }, + new() { ProvinceId = 24, ProvinceTitle = "گلستان", Cities = GetCities(24, "گرگان", "گنبد کاووس", "علی‌آباد") }, + new() { ProvinceId = 25, ProvinceTitle = "گیلان", Cities = GetCities(25, "رشت", "انزلی", "لاهیجان", "لنگرود") }, + new() { ProvinceId = 26, ProvinceTitle = "لرستان", Cities = GetCities(26, "خرم‌آباد", "بروجرد", "الیگودرز") }, + new() { ProvinceId = 27, ProvinceTitle = "مازندران", Cities = GetCities(27, "ساری", "بابل", "آمل", "قائم‌شهر", "چالوس") }, + new() { ProvinceId = 28, ProvinceTitle = "مرکزی", Cities = GetCities(28, "اراک", "ساوه", "خمین") }, + new() { ProvinceId = 29, ProvinceTitle = "هرمزگان", Cities = GetCities(29, "بندرعباس", "قشم", "کیش", "بندر لنگه") }, + new() { ProvinceId = 30, ProvinceTitle = "همدان", Cities = GetCities(30, "همدان", "ملایر", "نهاوند") }, + new() { ProvinceId = 31, ProvinceTitle = "یزد", Cities = GetCities(31, "یزد", "میبد", "اردکان") }, + }; + } + + private static List GetCities(int provinceId, params string[] cityNames) + { + var cities = new List(); + int cityId = provinceId * 100; // Simple ID generation: provinceId * 100 + index + for (int i = 0; i < cityNames.Length; i++) + { + cities.Add(new City + { + CityId = cityId + i + 1, + ProvinceId = provinceId, + CityTitle = cityNames[i] + }); + } + return cities; + } + } +}