using General_Ledger_Service.DTOs.Budget; using General_Ledger_Service.DTOs.Common; using General_Ledger_Service.Enums; using General_Ledger_Service.Exceptions; using General_Ledger_Service.Infra.UoW; using General_Ledger_Service.Interfaces.Repositories; using General_Ledger_Service.Interfaces.Services; using General_Ledger_Service.Models; namespace General_Ledger_Service.Services { public class BudgetService( IBudgetRepository budgetRepository, IFiscalCalendarRepository fiscalCalendarRepository, IAccountRepository accountRepository, ICostCenterRepository costCenterRepository, IAuditLogRepository auditLogRepository, IUnitOfWork unitOfWork) : IBudgetService { private readonly IBudgetRepository _budgetRepository = budgetRepository; private readonly IFiscalCalendarRepository _fiscalCalendarRepository = fiscalCalendarRepository; private readonly IAccountRepository _accountRepository = accountRepository; private readonly ICostCenterRepository _costCenterRepository = costCenterRepository; private readonly IAuditLogRepository _auditLogRepository = auditLogRepository; private readonly IUnitOfWork _unitOfWork = unitOfWork; public async Task CreateAsync(CreateBudgetRequest request) { _ = await _fiscalCalendarRepository.GetFiscalYearByIdAsync(request.FiscalYearId) ?? throw new NotFoundException("Fiscal year not found"); var budget = new Budget { FiscalYearId = request.FiscalYearId, Name = request.Name }; await _unitOfWork.BeginAsync(); try { await _budgetRepository.AddAsync(budget); await _unitOfWork.SaveChangesAsync(); await _auditLogRepository.AddAsync(new AuditLog { Category = AuditCategory.Administrative, EntityName = "Budget", EntityId = budget.BudgetId.ToString(), Action = AuditAction.Create, Description = $"Budget {budget.Name} created", PerformedBy = null }); await _unitOfWork.SaveChangesAsync(); await _unitOfWork.CommitAsync(); } catch { await _unitOfWork.RollbackAsync(); throw; } return ResponseHelpers.Created("Budget created successfully", budget); } public async Task AddLinesAsync(long budgetId, List request) { var budget = await _budgetRepository.GetByIdAsync(budgetId) ?? throw new NotFoundException("Budget not found"); var lines = new List(); foreach (var lineRequest in request) { var account = await _accountRepository.GetByCodeAsync(lineRequest.AccountCode) ?? throw new NotFoundException($"Account {lineRequest.AccountCode} not found"); _ = await _fiscalCalendarRepository.GetPeriodByIdAsync(lineRequest.PeriodId) ?? throw new NotFoundException($"Period {lineRequest.PeriodId} not found"); long? costCenterId = null; if (!string.IsNullOrWhiteSpace(lineRequest.CostCenterCode)) { var costCenter = await _costCenterRepository.GetByCodeAsync(lineRequest.CostCenterCode) ?? throw new NotFoundException($"Cost center {lineRequest.CostCenterCode} not found"); costCenterId = costCenter.CostCenterId; } lines.Add(new BudgetLine { BudgetId = budgetId, AccountId = account.AccountId, PeriodId = lineRequest.PeriodId, CostCenterId = costCenterId, BudgetedAmount = lineRequest.BudgetedAmount }); } await _unitOfWork.BeginAsync(); try { await _budgetRepository.AddLinesAsync(lines); await _unitOfWork.SaveChangesAsync(); await _auditLogRepository.AddAsync(new AuditLog { Category = AuditCategory.Administrative, EntityName = "Budget", EntityId = budget.BudgetId.ToString(), Action = AuditAction.Update, Description = $"{lines.Count} budget line(s) added to {budget.Name}", PerformedBy = null }); await _unitOfWork.SaveChangesAsync(); await _unitOfWork.CommitAsync(); } catch { await _unitOfWork.RollbackAsync(); throw; } return ResponseHelpers.Created("Budget lines added successfully", lines); } public async Task ListAsync() { var budgets = await _budgetRepository.GetAllAsync(); return ResponseHelpers.Ok("Budgets retrieved successfully", budgets); } } }