diff --git a/API/ROLAC.API/Data/DbSeeder.cs b/API/ROLAC.API/Data/DbSeeder.cs index e7ec773..0446072 100644 --- a/API/ROLAC.API/Data/DbSeeder.cs +++ b/API/ROLAC.API/Data/DbSeeder.cs @@ -137,6 +137,23 @@ public static class DbSeeder ("Other", "Gifts", "24"), ]; + private static readonly (string Code, string En, string Zh, string FormType, int Sort)[] Form1099BoxSeed = + [ + (Form1099.BoxNec1, "Nonemployee compensation", "非員工報酬", "1099-NEC", 1), + (Form1099.BoxMisc1, "Rents", "租金", "1099-MISC", 2), + ]; + + // Only service/rent subcategories get a box. Everything else stays unmapped (not reportable). + private static readonly (string GroupEn, string SubEn, string Code)[] Form1099SubMappingSeed = + [ + ("Personnel", "Honorarium", Form1099.BoxNec1), + ("Personnel", "Contract Labor", Form1099.BoxNec1), + ("Professional Services", "Legal", Form1099.BoxNec1), + ("Professional Services", "Accounting & Audit", Form1099.BoxNec1), + ("Professional Services", "Other Professional", Form1099.BoxNec1), + ("Facility", "Rent", Form1099.BoxMisc1), + ]; + // One-time corrections for subcategories that were mapped to the WRONG line in an earlier // seed. The normal mapping loop below only fills NULLs, so it cannot fix an existing bad // value — this block does. Idempotent: each row fires only while the subcategory still holds @@ -375,6 +392,25 @@ public static class DbSeeder await db.SaveChangesAsync(); } + public static async Task SeedForm1099BoxesAsync(AppDbContext db) + { + foreach (var (code, en, zh, formType, sort) in Form1099BoxSeed) + if (!await db.Form1099Boxes.AnyAsync(b => b.BoxCode == code)) + db.Form1099Boxes.Add(new Form1099Box + { BoxCode = code, Name_en = en, Name_zh = zh, FormType = formType, SortOrder = sort, IsActive = true }); + await db.SaveChangesAsync(); + + var boxesByCode = await db.Form1099Boxes.ToDictionaryAsync(b => b.BoxCode, b => b.Id); + var subs = await db.ExpenseSubCategories.Include(s => s.Group).ToListAsync(); + foreach (var (groupEn, subEn, code) in Form1099SubMappingSeed) + { + var sub = subs.FirstOrDefault(s => s.Group!.Name_en == groupEn && s.Name_en == subEn); + if (sub is not null && sub.Form1099BoxId is null && boxesByCode.TryGetValue(code, out var boxId)) + sub.Form1099BoxId = boxId; + } + await db.SaveChangesAsync(); + } + public static async Task SeedChurchProfileAsync(AppDbContext db) { // Singleton row used by the disbursement module (issuer info + check counter). @@ -454,6 +490,7 @@ public static class DbSeeder await SeedMinistriesAsync(db); await SeedExpenseCategoriesAsync(db); await SeedForm990ExpenseLinesAsync(db); + await SeedForm1099BoxesAsync(db); await SeedChurchProfileAsync(db); await SeedSiteSettingAsync(db); await SeedNotificationSettingAsync(db, config);