protected override async ValueTask <IResult <IEnumerable <AssetTotalModel> > > HandleImpl(GetAssetsTotalQuery request, CancellationToken cancellationToken)
        {
            var result = new List <AssetTotalModel>();

            var assets = await GetAsseets(request, cancellationToken)
                         .ConfigureAwait(false);

            var transactions = await GetTransactions(request, assets.Select(a => a.Id).ToArray(), cancellationToken)
                               .ConfigureAwait(false);

            var currency = await _currencyRepository.GetById(request.CurrencyId, cancellationToken)
                           .ConfigureAwait(false);

            foreach (var group in transactions.GroupBy(t => t.AssetId))
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(await FromCancellationToken(cancellationToken));
                }

                var asset = assets.FirstOrDefault(a => a.Id == group.Key);
                if (asset == null)
                {
                    continue;
                }

                decimal total = 0m;
                foreach (var transaction in group)
                {
                    var price = transaction.Amount * transaction.Rate;
                    total += transaction.CurrencyId != request.CurrencyId
                            ? await Exchange(transaction.Currency.Code, currency.Code, price, cancellationToken)
                             .ConfigureAwait(false)
                            : price;
                }
                var rate = await _forexService.GetPriceOf(asset.Code, currency.Code, cancellationToken)
                           .ConfigureAwait(false);

                var     amount   = group.Sum(t => t.Amount);
                decimal?totalNow = rate.IsSuccess ? amount * rate.Value.Rate : null;

                var model = new AssetTotalModel
                {
                    Id        = asset.Id,
                    Code      = asset.Code,
                    GroupId   = asset.GroupId,
                    Icon      = asset.Icon,
                    Name      = asset.Name,
                    Order     = asset.Order,
                    Symbol    = asset.Symbol,
                    SumAmount = amount,
                    Total     = total,
                    TotalNow  = totalNow,
                    Increase  = totalNow.HasValue ? CalculateProcent(total, totalNow.Value) : 0
                };

                if (asset.Group != null)
                {
                    model.Group = _mapper.Map <Group, GroupModel>(asset.Group);
                }

                result.Add(model);
            }

            return(result.AsResult());
        }
        protected override async ValueTask <IResult <IEnumerable <GroupedTransactionsModel> > > HandleImpl(GetAssetGroupedTransactionsQuery request, CancellationToken cancellationToken)
        {
            var result = new List <GroupedTransactionsModel>();
            IQueryable <Asset> query = _assetRepository.GetAll()
                                       .Include(a => a.Group);

            if (request.Filter != null)
            {
                if (request.Filter.AssetId.HasValue)
                {
                    query = query.Where(t => t.Id == request.Filter.AssetId.Value);
                }
                if (request.Filter.GroupId.HasValue)
                {
                    query = query.Where(t => t.GroupId == request.Filter.GroupId.Value);
                }
            }

            if (request.Order.HasValue)
            {
                query = request.Order.Value == General.Models.Order.Ascending
                        ? query.OrderBy(a => a.Name)
                        : query.OrderByDescending(a => a.Name);
            }

            var assets = await query
                         .ToListAsync(cancellationToken)
                         .ConfigureAwait(false);

            var transactions = _transactionRepository.GetAll();
            var user         = await _userRepository.GetMe(cancellationToken)
                               .ConfigureAwait(false);

            var toCurrencyId = user.GetSettings()?.PrefferedCurrency;
            var toCurrency   = toCurrencyId.HasValue
                    ? await _currencyRepository.GetById(toCurrencyId.Value, cancellationToken)
                    : null;

            var toCurrencyCode = toCurrency?.Code ?? _defaults.Currency;

            foreach (var asset in assets)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(await FromCancellationToken(cancellationToken));
                }

                var assetTransactions = transactions.Where(t => t.AssetId == asset.Id);

                if (request.Filter != null)
                {
                    if (request.Filter.From.HasValue)
                    {
                        assetTransactions = assetTransactions.Where(t => t.CreatedAt >= request.Filter.From.Value);
                    }
                    if (request.Filter.To.HasValue)
                    {
                        assetTransactions = assetTransactions.Where(t => t.CreatedAt <= request.Filter.To.Value);
                    }
                }

                if (!await assetTransactions.AnyAsync(cancellationToken).ConfigureAwait(false))
                {
                    continue;
                }

                var priceValue = await _forexService.GetPriceOf(asset.Code, toCurrencyCode, cancellationToken)
                                 .ConfigureAwait(false);

                var model = new GroupedTransactionsModel
                {
                    Asset  = _mapper.Map <Asset, AssetModel>(asset),
                    Amount = await transactions.SumAsync(t => t.Amount, cancellationToken)
                             .ConfigureAwait(false),
                    TotalBought = await transactions.SumAsync(t => t.Amount *t.Rate, cancellationToken)
                                  .ConfigureAwait(false),
                    ActualValue = priceValue.IsSuccess ? priceValue.Value.Rate : null
                };

                result.Add(model);
            }

            return(result.AsResult());
        }
        protected override async ValueTask <IResult <IEnumerable <GroupTotalModel> > > HandleImpl(GetGroupTotalQuery request, CancellationToken cancellationToken)
        {
            var result = new List <GroupTotalModel>();

            var currency = await _currencyRepository.GetById(request.CurrencyId, cancellationToken)
                           .ConfigureAwait(false);

            var groups = await GetGroups(request, cancellationToken)
                         .ConfigureAwait(false);

            var transactions = await GetTransactions(request, groups.Select(g => g.Id).ToArray(), cancellationToken)
                               .ConfigureAwait(false);

            foreach (var transGroup in transactions.GroupBy(t => t.Asset.GroupId))
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(await FromCancellationToken(cancellationToken));
                }

                var group = groups.FirstOrDefault(a => a.Id == transGroup.Key);
                if (group == null)
                {
                    continue;
                }

                decimal total    = 0m;
                decimal totalNow = 0m;
                foreach (var transaction in transGroup)
                {
                    var price = transaction.Amount * transaction.Rate;
                    total += transaction.CurrencyId != request.CurrencyId
                            ? await Exchange(transaction.Currency.Code, currency.Code, price, cancellationToken)
                             .ConfigureAwait(false)
                            : price;
                }
                foreach (var tranAsseet in transGroup.GroupBy(t => t.AssetId))
                {
                    var asset = tranAsseet.First().Asset;
                    var rate  = await _forexService.GetPriceOf(asset.Code, currency.Code, cancellationToken)
                                .ConfigureAwait(false);

                    totalNow += rate.IsSuccess ? tranAsseet.Sum(t => t.Amount) * rate.Value.Rate : 0;
                }
                var amount = transGroup.Sum(t => t.Amount);

                var model = new GroupTotalModel
                {
                    Id        = group.Id,
                    Code      = group.Code,
                    Name      = group.Name,
                    SumAmount = amount,
                    Total     = total,
                    TotalNow  = totalNow != 0 ? totalNow : null,
                    Increase  = CalculateProcent(total, totalNow)
                };

                result.Add(model);
            }

            return(result.AsResult());
        }