namespace MyOffice.Services.Dashboard; using Core.Extensions; using Data.Repositories.Account; using Data.Repositories.Currency; using MyOffice.Data.Models.Accounts; using MyOffice.Services.Dashboard.Domain; public class DashboardService { private readonly IAccountRepository _accountRepository; private readonly ICurrencyRateRepository _currencyRateRepository; public DashboardService( IAccountRepository accountRepository, ICurrencyRateRepository currencyRateRepository ) { _accountRepository = accountRepository; _currencyRateRepository = currencyRateRepository; } public async Task GetDashboardRestDataAsync( Guid userId, CancellationToken cancellationToken = default ) { var rests = await _accountRepository.GetRestAtDateAsync(userId, DateTime.UtcNow, cancellationToken); return new DashboardData { Balance = rests .Where(x => (x.Type == AccountAccessTypeEnum.balance || x.Type == AccountAccessTypeEnum.credit) && x.CurrencyRate.HasValue) .Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)), BalanceDebit = rests .Where(x => x.Type == AccountAccessTypeEnum.balance && x.CurrencyRate.HasValue) .Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)), BalanceCredit = rests .Where(x => x.Type == AccountAccessTypeEnum.credit && x.CurrencyRate.HasValue) .Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)), BalanceRests = rests .Where(x => x.Type == AccountAccessTypeEnum.balance) .Where(x => x.CurrencyRate.HasValue && x.Balance.HasValue && x.Balance != 0) .Select(x => new DashboardRestData { Id = x.Id, Name = x.Name, Balance = x.Balance, CurrencyName = x.CurrencyName!, CurrencyShortName = x.CurrencyShortName!, CurrencyRate = x.CurrencyRate, CurrencyQuantity = x.CurrencyQuantity, }) .OrderByDescending(x => x.BalanceAtRate) .ToList(), }; } public async Task GetDashboardIncomeDataAsync( Guid userId, DateTime from, DateTime to, Guid? category, CancellationToken cancellationToken = default ) { var data = category.HasValue ? await _accountRepository.GetIncomeByCategoryAsync(userId, category.Value, from.ToUtc(), to.ToUtc(), cancellationToken) : await _accountRepository.GetIncomeByCategoriesAsync(userId, from.ToUtc(), to.ToUtc(), cancellationToken); data = data .Where(x => x.Amount != 0) .ToList(); var currencies = data .Select(x => x.CurrencyId) .Distinct() .ToList(); var rates = (await _currencyRateRepository.GetLastRatesAsync(userId, currencies, to.ToUtc(), cancellationToken)) .ToDictionary(x => x.Key, x => x.Value.Rate * x.Value.Quantity); return BuildIncomeData(data, rates); } public async Task GetDashboardOutcomeDataAsync( Guid userId, DateTime from, DateTime to, Guid? category, CancellationToken cancellationToken = default ) { var data = category.HasValue ? await _accountRepository.GetOutcomeByCategoryAsync(userId, category.Value, from.ToUtc(), to.ToUtc(), cancellationToken) : await _accountRepository.GetOutcomeByCategoriesAsync(userId, from.ToUtc(), to.ToUtc(), cancellationToken); data = data .Where(x => x.Amount != 0) .ToList(); var currencies = data .Select(x => x.CurrencyId) .Distinct() .ToList(); var rates = (await _currencyRateRepository.GetLastRatesAsync(userId, currencies, to.ToUtc(), cancellationToken)) .ToDictionary(x => x.Key, x => x.Value.Rate * x.Value.Quantity); return BuildIncomeData(data, rates); } private static DashboardIncomeData BuildIncomeData( List data, Dictionary rates ) { return new DashboardIncomeData { Data = data.Select(x => new { Id = x.Id.ToShort(), Name = x.Name, ValueRaw = x.Amount, Value = x.Amount * rates.FirstOrDefault(r => r.Key == x.CurrencyId).Value, }) .GroupBy(x => new { x.Id, x.Name }) .Select(x => new DashboardIncomeDataItem { Id = x.Key.Id, Name = x.Key.Name, Value = x.Sum(s => s.Value), ValueRaw = x.Sum(s => s.ValueRaw), }) .OrderBy(x => x.Name) .ToList(), Details = data.Select(x => new { Id = x.CurrencyId, Name = x.CurrencyName, ValueRaw = x.Amount, Value = x.Amount * rates.FirstOrDefault(r => r.Key == x.CurrencyId).Value, }) .GroupBy(x => new { x.Id, x.Name }) .Select(x => new DashboardIncomeDataItem { Id = x.Key.Id, Name = x.Key.Name, Value = x.Sum(s => s.Value), ValueRaw = x.Sum(s => s.ValueRaw), }) .OrderBy(x => x.Name) .ToList(), }; } }