Improve filtering (#901)
This commit is contained in:
parent
dfa67b275c
commit
c1d460cead
@ -1,5 +1,6 @@
|
||||
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
|
||||
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
||||
import { Filter } from '@ghostfolio/common/interfaces';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Account, Order, Platform, Prisma } from '@prisma/client';
|
||||
import Big from 'big.js';
|
||||
@ -102,22 +103,39 @@ export class AccountService {
|
||||
});
|
||||
}
|
||||
|
||||
public async getCashDetails(
|
||||
aUserId: string,
|
||||
aCurrency: string
|
||||
): Promise<CashDetails> {
|
||||
public async getCashDetails({
|
||||
currency,
|
||||
filters = [],
|
||||
userId
|
||||
}: {
|
||||
currency: string;
|
||||
filters?: Filter[];
|
||||
userId: string;
|
||||
}): Promise<CashDetails> {
|
||||
let totalCashBalanceInBaseCurrency = new Big(0);
|
||||
|
||||
const accounts = await this.accounts({
|
||||
where: { userId: aUserId }
|
||||
});
|
||||
const where: Prisma.AccountWhereInput = { userId };
|
||||
|
||||
if (filters?.length > 0) {
|
||||
where.id = {
|
||||
in: filters
|
||||
.filter(({ type }) => {
|
||||
return type === 'account';
|
||||
})
|
||||
.map(({ id }) => {
|
||||
return id;
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
const accounts = await this.accounts({ where });
|
||||
|
||||
for (const account of accounts) {
|
||||
totalCashBalanceInBaseCurrency = totalCashBalanceInBaseCurrency.plus(
|
||||
this.exchangeRateDataService.toCurrency(
|
||||
account.balance,
|
||||
account.currency,
|
||||
aCurrency
|
||||
currency
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -182,8 +182,8 @@ export class PortfolioController {
|
||||
this.request.user.subscription.type === 'Basic';
|
||||
|
||||
return {
|
||||
accounts,
|
||||
hasError,
|
||||
accounts: filters.length === 0 ? accounts : {},
|
||||
holdings: isBasicUser ? {} : holdings
|
||||
};
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ import {
|
||||
subDays,
|
||||
subYears
|
||||
} from 'date-fns';
|
||||
import { isEmpty, sortBy, uniqBy } from 'lodash';
|
||||
import { isEmpty, sortBy, uniq, uniqBy } from 'lodash';
|
||||
|
||||
import {
|
||||
HistoricalDataContainer,
|
||||
@ -344,10 +344,11 @@ export class PortfolioService {
|
||||
startDate
|
||||
);
|
||||
|
||||
const cashDetails = await this.accountService.getCashDetails(
|
||||
const cashDetails = await this.accountService.getCashDetails({
|
||||
userId,
|
||||
userCurrency
|
||||
);
|
||||
currency: userCurrency,
|
||||
filters: aFilters
|
||||
});
|
||||
|
||||
const holdings: PortfolioDetails['holdings'] = {};
|
||||
const totalInvestment = currentPositions.totalInvestment.plus(
|
||||
@ -440,26 +441,26 @@ export class PortfolioService {
|
||||
};
|
||||
}
|
||||
|
||||
const cashPositions = await this.getCashPositions({
|
||||
cashDetails,
|
||||
emergencyFund,
|
||||
userCurrency,
|
||||
investment: totalInvestment,
|
||||
value: totalValue
|
||||
});
|
||||
|
||||
if (aFilters?.length === 0) {
|
||||
const cashPositions = await this.getCashPositions({
|
||||
cashDetails,
|
||||
emergencyFund,
|
||||
userCurrency,
|
||||
investment: totalInvestment,
|
||||
value: totalValue
|
||||
});
|
||||
|
||||
for (const symbol of Object.keys(cashPositions)) {
|
||||
holdings[symbol] = cashPositions[symbol];
|
||||
}
|
||||
}
|
||||
|
||||
const accounts = await this.getValueOfAccounts(
|
||||
const accounts = await this.getValueOfAccounts({
|
||||
orders,
|
||||
userId,
|
||||
portfolioItemsNow,
|
||||
userCurrency,
|
||||
userId
|
||||
);
|
||||
filters: aFilters
|
||||
});
|
||||
|
||||
return { accounts, holdings, hasErrors: currentPositions.hasErrors };
|
||||
}
|
||||
@ -890,12 +891,11 @@ export class PortfolioService {
|
||||
for (const position of currentPositions.positions) {
|
||||
portfolioItemsNow[position.symbol] = position;
|
||||
}
|
||||
const accounts = await this.getValueOfAccounts(
|
||||
const accounts = await this.getValueOfAccounts({
|
||||
orders,
|
||||
portfolioItemsNow,
|
||||
currency,
|
||||
userId
|
||||
);
|
||||
});
|
||||
return {
|
||||
rules: {
|
||||
accountClusterRisk: await this.rulesService.evaluate(
|
||||
@ -957,10 +957,10 @@ export class PortfolioService {
|
||||
|
||||
const performanceInformation = await this.getPerformance(aImpersonationId);
|
||||
|
||||
const { balanceInBaseCurrency } = await this.accountService.getCashDetails(
|
||||
const { balanceInBaseCurrency } = await this.accountService.getCashDetails({
|
||||
userId,
|
||||
userCurrency
|
||||
);
|
||||
currency: userCurrency
|
||||
});
|
||||
const orders = await this.orderService.getOrders({
|
||||
userCurrency,
|
||||
userId
|
||||
@ -1253,21 +1253,40 @@ export class PortfolioService {
|
||||
portfolioCalculator.computeTransactionPoints();
|
||||
|
||||
return {
|
||||
transactionPoints: portfolioCalculator.getTransactionPoints(),
|
||||
orders,
|
||||
portfolioOrders
|
||||
portfolioOrders,
|
||||
transactionPoints: portfolioCalculator.getTransactionPoints()
|
||||
};
|
||||
}
|
||||
|
||||
private async getValueOfAccounts(
|
||||
orders: OrderWithAccount[],
|
||||
portfolioItemsNow: { [p: string]: TimelinePosition },
|
||||
userCurrency: string,
|
||||
userId: string
|
||||
) {
|
||||
private async getValueOfAccounts({
|
||||
filters = [],
|
||||
orders,
|
||||
portfolioItemsNow,
|
||||
userId
|
||||
}: {
|
||||
filters?: Filter[];
|
||||
orders: OrderWithAccount[];
|
||||
portfolioItemsNow: { [p: string]: TimelinePosition };
|
||||
userId: string;
|
||||
}) {
|
||||
const accounts: PortfolioDetails['accounts'] = {};
|
||||
|
||||
const currentAccounts = await this.accountService.getAccounts(userId);
|
||||
let currentAccounts = [];
|
||||
|
||||
if (filters.length === 0) {
|
||||
currentAccounts = await this.accountService.getAccounts(userId);
|
||||
} else {
|
||||
const accountIds = uniq(
|
||||
orders.map(({ accountId }) => {
|
||||
return accountId;
|
||||
})
|
||||
);
|
||||
|
||||
currentAccounts = await this.accountService.accounts({
|
||||
where: { id: { in: accountIds } }
|
||||
});
|
||||
}
|
||||
|
||||
for (const account of currentAccounts) {
|
||||
const ordersByAccount = orders.filter(({ accountId }) => {
|
||||
|
@ -155,15 +155,17 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
if (state?.user) {
|
||||
this.user = state.user;
|
||||
|
||||
const accountFilters: Filter[] = this.user.accounts.map(
|
||||
({ id, name }) => {
|
||||
const accountFilters: Filter[] = this.user.accounts
|
||||
.filter(({ accountType }) => {
|
||||
return accountType === 'SECURITIES';
|
||||
})
|
||||
.map(({ id, name }) => {
|
||||
return {
|
||||
id: id,
|
||||
id,
|
||||
label: name,
|
||||
type: 'account'
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const tagFilters: Filter[] = this.user.tags.map(({ id, name }) => {
|
||||
return {
|
||||
@ -347,17 +349,12 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
this.activeFilters?.length === 0 ||
|
||||
position.assetSubClass !== AssetClass.CASH
|
||||
) {
|
||||
this.symbols[prettifySymbol(symbol)] = {
|
||||
dataSource: position.dataSource,
|
||||
name: position.name,
|
||||
symbol: prettifySymbol(symbol),
|
||||
value: aPeriod === 'original' ? position.investment : position.value
|
||||
};
|
||||
}
|
||||
this.symbols[prettifySymbol(symbol)] = {
|
||||
dataSource: position.dataSource,
|
||||
name: position.name,
|
||||
symbol: prettifySymbol(symbol),
|
||||
value: aPeriod === 'original' ? position.investment : position.value
|
||||
};
|
||||
}
|
||||
|
||||
const marketsTotal =
|
||||
|
@ -48,7 +48,7 @@ export class ActivitiesFilterComponent implements OnChanges, OnDestroy {
|
||||
public constructor() {
|
||||
this.searchControl.valueChanges
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe((currentFilter: string) => {
|
||||
.subscribe((currentFilter: Filter) => {
|
||||
if (currentFilter) {
|
||||
this.filters$.next(
|
||||
this.allFilters
|
||||
@ -61,7 +61,7 @@ export class ActivitiesFilterComponent implements OnChanges, OnDestroy {
|
||||
.filter((filter) => {
|
||||
return filter.label
|
||||
.toLowerCase()
|
||||
.startsWith(currentFilter?.toLowerCase());
|
||||
.startsWith(currentFilter.label.toLowerCase());
|
||||
})
|
||||
.sort((a, b) => a.label.localeCompare(b.label))
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user