Browse Source

Resolve asset class labels, exclude liabilities

pull/3123/head
Thomas Kaul 1 year ago
parent
commit
ed67cdfc8b
  1. 1
      apps/api/src/app/portfolio/portfolio.controller.ts
  2. 21
      apps/api/src/app/portfolio/portfolio.service.ts
  3. 2
      apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts
  4. 53
      apps/client/src/app/services/data.service.ts
  5. 6
      libs/common/src/lib/helper.ts

1
apps/api/src/app/portfolio/portfolio.controller.ts

@ -110,6 +110,7 @@ export class PortfolioController {
filters, filters,
impersonationId, impersonationId,
userId: this.request.user.id, userId: this.request.user.id,
withLiabilities: true,
withSummary: true withSummary: true
}); });

21
apps/api/src/app/portfolio/portfolio.service.ts

@ -24,7 +24,12 @@ import {
MAX_CHART_ITEMS, MAX_CHART_ITEMS,
UNKNOWN_KEY UNKNOWN_KEY
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { DATE_FORMAT, getSum, parseDate } from '@ghostfolio/common/helper'; import {
DATE_FORMAT,
getAllActivityTypes,
getSum,
parseDate
} from '@ghostfolio/common/helper';
import { import {
Accounts, Accounts,
EnhancedSymbolProfile, EnhancedSymbolProfile,
@ -141,7 +146,8 @@ export class PortfolioService {
filters, filters,
withExcludedAccounts, withExcludedAccounts,
impersonationId: userId, impersonationId: userId,
userId: this.request.user.id userId: this.request.user.id,
withLiabilities: true
}) })
]); ]);
@ -333,6 +339,7 @@ export class PortfolioService {
impersonationId, impersonationId,
userId, userId,
withExcludedAccounts = false, withExcludedAccounts = false,
withLiabilities = false,
withSummary = false withSummary = false
}: { }: {
dateRange?: DateRange; dateRange?: DateRange;
@ -340,6 +347,7 @@ export class PortfolioService {
impersonationId: string; impersonationId: string;
userId: string; userId: string;
withExcludedAccounts?: boolean; withExcludedAccounts?: boolean;
withLiabilities?: boolean;
withSummary?: boolean; withSummary?: boolean;
}): Promise<PortfolioDetails & { hasErrors: boolean }> { }): Promise<PortfolioDetails & { hasErrors: boolean }> {
userId = await this.getUserId(impersonationId, userId); userId = await this.getUserId(impersonationId, userId);
@ -354,7 +362,12 @@ export class PortfolioService {
await this.getTransactionPoints({ await this.getTransactionPoints({
filters, filters,
userId, userId,
withExcludedAccounts withExcludedAccounts,
types: withLiabilities
? undefined
: getAllActivityTypes().filter((activityType) => {
return activityType !== 'LIABILITY';
})
}); });
const portfolioCalculator = new PortfolioCalculator({ const portfolioCalculator = new PortfolioCalculator({
@ -1949,7 +1962,7 @@ export class PortfolioService {
private async getTransactionPoints({ private async getTransactionPoints({
filters, filters,
includeDrafts = false, includeDrafts = false,
types = ['BUY', 'DIVIDEND', 'ITEM', 'LIABILITY', 'SELL'], types = getAllActivityTypes(),
userId, userId,
withExcludedAccounts = false withExcludedAccounts = false
}: { }: {

2
apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts

@ -96,7 +96,7 @@ export class HoldingsPageComponent implements OnDestroy, OnInit {
} }
private fetchHoldings() { private fetchHoldings() {
return this.dataService.fetchHoldings({ return this.dataService.fetchPortfolioHoldings({
filters: this.userService.getFilters() filters: this.userService.getFilters()
}); });
} }

53
apps/client/src/app/services/data.service.ts

@ -230,19 +230,6 @@ export class DataService {
); );
} }
public fetchHoldings({
filters
}: {
filters?: Filter[];
} = {}) {
return this.http.get<PortfolioHoldingsResponse>(
'/api/v1/portfolio/holdings',
{
params: this.buildFiltersAsQueryParams({ filters })
}
);
}
public deleteAccess(aId: string) { public deleteAccess(aId: string) {
return this.http.delete<any>(`/api/v1/access/${aId}`); return this.http.delete<any>(`/api/v1/access/${aId}`);
} }
@ -448,6 +435,46 @@ export class DataService {
); );
} }
public fetchPortfolioHoldings({
filters
}: {
filters?: Filter[];
} = {}) {
return this.http
.get<PortfolioHoldingsResponse>('/api/v1/portfolio/holdings', {
params: this.buildFiltersAsQueryParams({ filters })
})
.pipe(
map((response) => {
if (response.holdings) {
for (const symbol of Object.keys(response.holdings)) {
response.holdings[symbol].assetClassLabel = translate(
response.holdings[symbol].assetClass
);
response.holdings[symbol].assetSubClassLabel = translate(
response.holdings[symbol].assetSubClass
);
response.holdings[symbol].dateOfFirstActivity = response.holdings[
symbol
].dateOfFirstActivity
? parseISO(response.holdings[symbol].dateOfFirstActivity)
: undefined;
response.holdings[symbol].value = isNumber(
response.holdings[symbol].value
)
? response.holdings[symbol].value
: response.holdings[symbol].valueInPercentage;
}
}
return response;
})
);
}
public fetchPortfolioPerformance({ public fetchPortfolioPerformance({
filters, filters,
range, range,

6
libs/common/src/lib/helper.ts

@ -1,6 +1,6 @@
import * as currencies from '@dinero.js/currencies'; import * as currencies from '@dinero.js/currencies';
import { NumberParser } from '@internationalized/number'; import { NumberParser } from '@internationalized/number';
import { DataSource, MarketData } from '@prisma/client'; import { DataSource, MarketData, Type as ActivityType } from '@prisma/client';
import Big from 'big.js'; import Big from 'big.js';
import { import {
getDate, getDate,
@ -138,6 +138,10 @@ export function extractNumberFromString({
} }
} }
export function getAllActivityTypes(): ActivityType[] {
return ['BUY', 'DIVIDEND', 'FEE', 'ITEM', 'LIABILITY', 'SELL'];
}
export function getAssetProfileIdentifier({ dataSource, symbol }: UniqueAsset) { export function getAssetProfileIdentifier({ dataSource, symbol }: UniqueAsset) {
return `${dataSource}-${symbol}`; return `${dataSource}-${symbol}`;
} }

Loading…
Cancel
Save