using Microsoft.EntityFrameworkCore; using ROLAC.API.Data; using ROLAC.API.DTOs.Expense; using ROLAC.API.Entities; namespace ROLAC.API.Services; public class ExpenseCategoryService : IExpenseCategoryService { private readonly AppDbContext _db; public ExpenseCategoryService(AppDbContext db) => _db = db; public async Task> GetAllAsync(bool includeInactive) { var groups = await _db.ExpenseCategoryGroups.AsNoTracking() .Where(g => includeInactive || g.IsActive) .OrderBy(g => g.SortOrder).ThenBy(g => g.Name_en) .ToListAsync(); var subs = await _db.ExpenseSubCategories.AsNoTracking() .Where(s => includeInactive || s.IsActive) .OrderBy(s => s.SortOrder).ThenBy(s => s.Name_en) .ToListAsync(); return groups.Select(g => new ExpenseCategoryGroupDto { Id = g.Id, Name_en = g.Name_en, Name_zh = g.Name_zh, SortOrder = g.SortOrder, IsActive = g.IsActive, SubCategories = subs.Where(s => s.GroupId == g.Id).Select(s => new ExpenseSubCategoryDto { Id = s.Id, GroupId = s.GroupId, Name_en = s.Name_en, Name_zh = s.Name_zh, SortOrder = s.SortOrder, IsActive = s.IsActive, }).ToList(), }).ToList(); } public async Task CreateGroupAsync(CreateExpenseGroupRequest r) { var g = new ExpenseCategoryGroup { Name_en = r.Name_en, Name_zh = r.Name_zh, SortOrder = r.SortOrder, IsActive = true }; _db.ExpenseCategoryGroups.Add(g); await _db.SaveChangesAsync(); return g.Id; } public async Task UpdateGroupAsync(int id, UpdateExpenseGroupRequest r) { var g = await _db.ExpenseCategoryGroups.FindAsync(id) ?? throw new KeyNotFoundException($"ExpenseCategoryGroup {id} not found."); g.Name_en = r.Name_en; g.Name_zh = r.Name_zh; g.SortOrder = r.SortOrder; g.IsActive = r.IsActive; await _db.SaveChangesAsync(); } public async Task DeactivateGroupAsync(int id) { var g = await _db.ExpenseCategoryGroups.FindAsync(id) ?? throw new KeyNotFoundException($"ExpenseCategoryGroup {id} not found."); g.IsActive = false; await _db.SaveChangesAsync(); } public async Task CreateSubCategoryAsync(CreateExpenseSubCategoryRequest r) { var exists = await _db.ExpenseCategoryGroups.AnyAsync(g => g.Id == r.GroupId); if (!exists) throw new KeyNotFoundException($"ExpenseCategoryGroup {r.GroupId} not found."); var s = new ExpenseSubCategory { GroupId = r.GroupId, Name_en = r.Name_en, Name_zh = r.Name_zh, SortOrder = r.SortOrder, IsActive = true }; _db.ExpenseSubCategories.Add(s); await _db.SaveChangesAsync(); return s.Id; } public async Task UpdateSubCategoryAsync(int id, UpdateExpenseSubCategoryRequest r) { var s = await _db.ExpenseSubCategories.FindAsync(id) ?? throw new KeyNotFoundException($"ExpenseSubCategory {id} not found."); s.GroupId = r.GroupId; s.Name_en = r.Name_en; s.Name_zh = r.Name_zh; s.SortOrder = r.SortOrder; s.IsActive = r.IsActive; await _db.SaveChangesAsync(); } public async Task DeactivateSubCategoryAsync(int id) { var s = await _db.ExpenseSubCategories.FindAsync(id) ?? throw new KeyNotFoundException($"ExpenseSubCategory {id} not found."); s.IsActive = false; await _db.SaveChangesAsync(); } }