using Duempelkas.App.Services; using Duempelkas.App.Services.Models; using Duempelkas.Domain.Enums; using Duempelkas.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; namespace Duempelkas.Infrastructure.Services; public class BalanceQueryService : IBalanceQueryService { private readonly IDbContextFactory _dbFactory; public BalanceQueryService(IDbContextFactory dbFactory) => _dbFactory = dbFactory; public async Task GetAccountBalanceAsync(int accountId, int? year = null) { await using var db = await _dbFactory.CreateDbContextAsync(); var account = await db.Accounts .Include(a => a.Entries) .FirstOrDefaultAsync(a => a.Id == accountId) ?? throw new InvalidOperationException($"Konto {accountId} nicht gefunden."); var selectedYear = year ?? DateTime.Now.Year; var activeEntries = account.Entries.Where(e => !e.IsDeleted).ToList(); var totalIncome = activeEntries.Where(e => e.Type == EntryType.Income).Sum(e => e.Amount); var totalExpense = activeEntries.Where(e => e.Type == EntryType.Expense).Sum(e => e.Amount); var selectedYearIncome = activeEntries .Where(e => e.Type == EntryType.Income && e.Date.Year == selectedYear) .Sum(e => e.Amount); var selectedYearExpense = activeEntries .Where(e => e.Type == EntryType.Expense && e.Date.Year == selectedYear) .Sum(e => e.Amount); var selectedYearCarryover = account.CarryoverBalance + activeEntries .Where(e => e.Date.Year < selectedYear) .Sum(e => e.Type == EntryType.Income ? e.Amount : -e.Amount); var totalBalance = year.HasValue ? selectedYearCarryover + selectedYearIncome - selectedYearExpense : account.CarryoverBalance + totalIncome - totalExpense; return new AccountBalanceDto( year.HasValue ? selectedYearCarryover : account.CarryoverBalance, totalIncome, totalExpense, selectedYearIncome, selectedYearExpense, totalBalance); } }