Browse Source

Rename allocationCurrent, remove allocationInvestment

pull/1620/head
Thomas 3 years ago
parent
commit
5d4eadeceb
  1. 2
      apps/api/src/app/portfolio/portfolio.controller.ts
  2. 13
      apps/api/src/app/portfolio/portfolio.service.ts
  3. 70
      apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
  4. 48
      apps/client/src/app/pages/portfolio/allocations/allocations-page.html
  5. 2
      apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts
  6. 2
      apps/client/src/app/pages/public/public-page.component.ts
  7. 3
      libs/common/src/lib/interfaces/portfolio-position.interface.ts
  8. 2
      libs/common/src/lib/interfaces/portfolio-public-details.interface.ts
  9. 6
      libs/ui/src/lib/holdings-table/holdings-table.component.html
  10. 2
      libs/ui/src/lib/holdings-table/holdings-table.component.ts

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

@ -441,7 +441,7 @@ export class PortfolioController {
for (const [symbol, portfolioPosition] of Object.entries(holdings)) { for (const [symbol, portfolioPosition] of Object.entries(holdings)) {
portfolioPublicDetails.holdings[symbol] = { portfolioPublicDetails.holdings[symbol] = {
allocationCurrent: portfolioPosition.value / totalValue, allocationInPercentage: portfolioPosition.value / totalValue,
countries: hasDetails ? portfolioPosition.countries : [], countries: hasDetails ? portfolioPosition.countries : [],
currency: hasDetails ? portfolioPosition.currency : undefined, currency: hasDetails ? portfolioPosition.currency : undefined,
dataSource: portfolioPosition.dataSource, dataSource: portfolioPosition.dataSource,

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

@ -537,12 +537,9 @@ export class PortfolioService {
holdings[item.symbol] = { holdings[item.symbol] = {
markets, markets,
allocationCurrent: filteredValueInBaseCurrency.eq(0) allocationInPercentage: filteredValueInBaseCurrency.eq(0)
? 0 ? 0
: value.div(filteredValueInBaseCurrency).toNumber(), : value.div(filteredValueInBaseCurrency).toNumber(),
allocationInvestment: item.investment
.div(totalInvestmentInBaseCurrency)
.toNumber(),
assetClass: symbolProfile.assetClass, assetClass: symbolProfile.assetClass,
assetSubClass: symbolProfile.assetSubClass, assetSubClass: symbolProfile.assetSubClass,
countries: symbolProfile.countries, countries: symbolProfile.countries,
@ -1258,12 +1255,9 @@ export class PortfolioService {
for (const symbol of Object.keys(cashPositions)) { for (const symbol of Object.keys(cashPositions)) {
// Calculate allocations for each currency // Calculate allocations for each currency
cashPositions[symbol].allocationCurrent = value.gt(0) cashPositions[symbol].allocationInPercentage = value.gt(0)
? new Big(cashPositions[symbol].value).div(value).toNumber() ? new Big(cashPositions[symbol].value).div(value).toNumber()
: 0; : 0;
cashPositions[symbol].allocationInvestment = investment.gt(0)
? new Big(cashPositions[symbol].investment).div(investment).toNumber()
: 0;
} }
return cashPositions; return cashPositions;
@ -1430,8 +1424,7 @@ export class PortfolioService {
}): PortfolioPosition { }): PortfolioPosition {
return { return {
currency, currency,
allocationCurrent: 0, allocationInPercentage: 0,
allocationInvestment: 0,
assetClass: AssetClass.CASH, assetClass: AssetClass.CASH,
assetSubClass: AssetClass.CASH, assetSubClass: AssetClass.CASH,
countries: [], countries: [],

70
apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts

@ -18,7 +18,7 @@ import {
User User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { Market, ToggleOption } from '@ghostfolio/common/types'; import { Market } from '@ghostfolio/common/types';
import { translate } from '@ghostfolio/ui/i18n'; import { translate } from '@ghostfolio/ui/i18n';
import { Account, AssetClass, DataSource } from '@prisma/client'; import { Account, AssetClass, DataSource } from '@prisma/client';
import { DeviceDetectorService } from 'ngx-device-detector'; import { DeviceDetectorService } from 'ngx-device-detector';
@ -53,11 +53,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
public markets: { public markets: {
[key in Market]: { name: string; value: number }; [key in Market]: { name: string; value: number };
}; };
public period = 'current';
public periodOptions: ToggleOption[] = [
{ label: $localize`Initial`, value: 'original' },
{ label: $localize`Current`, value: 'current' }
];
public placeholder = ''; public placeholder = '';
public portfolioDetails: PortfolioDetails; public portfolioDetails: PortfolioDetails;
public positions: { public positions: {
@ -146,7 +141,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
.subscribe((portfolioDetails) => { .subscribe((portfolioDetails) => {
this.portfolioDetails = portfolioDetails; this.portfolioDetails = portfolioDetails;
this.initializeAnalysisData(this.period); this.initializeAnalysisData();
this.isLoading = false; this.isLoading = false;
@ -248,7 +243,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
}; };
} }
public initializeAnalysisData(aPeriod: string) { public initializeAnalysisData() {
this.initialize(); this.initialize();
for (const [id, { current, name, original }] of Object.entries( for (const [id, { current, name, original }] of Object.entries(
@ -257,7 +252,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
this.accounts[id] = { this.accounts[id] = {
id, id,
name, name,
value: aPeriod === 'original' ? original : current value: current
}; };
} }
@ -266,19 +261,11 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
)) { )) {
let value = 0; let value = 0;
if (aPeriod === 'original') {
if (this.hasImpersonationId) {
value = position.allocationInvestment;
} else {
value = position.investment;
}
} else {
if (this.hasImpersonationId) { if (this.hasImpersonationId) {
value = position.allocationCurrent; value = position.allocationInPercentage;
} else { } else {
value = position.value; value = position.value;
} }
}
this.positions[symbol] = { this.positions[symbol] = {
value, value,
@ -294,14 +281,11 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
if (position.countries.length > 0) { if (position.countries.length > 0) {
this.markets.developedMarkets.value += this.markets.developedMarkets.value +=
position.markets.developedMarkets * position.markets.developedMarkets * position.value;
(aPeriod === 'original' ? position.investment : position.value);
this.markets.emergingMarkets.value += this.markets.emergingMarkets.value +=
position.markets.emergingMarkets * position.markets.emergingMarkets * position.value;
(aPeriod === 'original' ? position.investment : position.value);
this.markets.otherMarkets.value += this.markets.otherMarkets.value +=
position.markets.otherMarkets * position.markets.otherMarkets * position.value;
(aPeriod === 'original' ? position.investment : position.value);
for (const country of position.countries) { for (const country of position.countries) {
const { code, continent, name, weight } = country; const { code, continent, name, weight } = country;
@ -311,11 +295,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
} else { } else {
this.continents[continent] = { this.continents[continent] = {
name: continent, name: continent,
value: value: weight * this.portfolioDetails.holdings[symbol].value
weight *
(aPeriod === 'original'
? this.portfolioDetails.holdings[symbol].investment
: this.portfolioDetails.holdings[symbol].value)
}; };
} }
@ -324,24 +304,16 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
} else { } else {
this.countries[code] = { this.countries[code] = {
name, name,
value: value: weight * this.portfolioDetails.holdings[symbol].value
weight *
(aPeriod === 'original'
? this.portfolioDetails.holdings[symbol].investment
: this.portfolioDetails.holdings[symbol].value)
}; };
} }
} }
} else { } else {
this.continents[UNKNOWN_KEY].value += this.continents[UNKNOWN_KEY].value +=
aPeriod === 'original' this.portfolioDetails.holdings[symbol].value;
? this.portfolioDetails.holdings[symbol].investment
: this.portfolioDetails.holdings[symbol].value;
this.countries[UNKNOWN_KEY].value += this.countries[UNKNOWN_KEY].value +=
aPeriod === 'original' this.portfolioDetails.holdings[symbol].value;
? this.portfolioDetails.holdings[symbol].investment
: this.portfolioDetails.holdings[symbol].value;
} }
if (position.sectors.length > 0) { if (position.sectors.length > 0) {
@ -353,19 +325,13 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
} else { } else {
this.sectors[name] = { this.sectors[name] = {
name, name,
value: value: weight * this.portfolioDetails.holdings[symbol].value
weight *
(aPeriod === 'original'
? this.portfolioDetails.holdings[symbol].investment
: this.portfolioDetails.holdings[symbol].value)
}; };
} }
} }
} else { } else {
this.sectors[UNKNOWN_KEY].value += this.sectors[UNKNOWN_KEY].value +=
aPeriod === 'original' this.portfolioDetails.holdings[symbol].value;
? this.portfolioDetails.holdings[symbol].investment
: this.portfolioDetails.holdings[symbol].value;
} }
} }
@ -373,7 +339,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
dataSource: position.dataSource, dataSource: position.dataSource,
name: position.name, name: position.name,
symbol: prettifySymbol(symbol), symbol: prettifySymbol(symbol),
value: aPeriod === 'original' ? position.investment : position.value value: position.value
}; };
} }
@ -398,12 +364,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
} }
} }
public onChangePeriod(aValue: string) {
this.period = aValue;
this.initializeAnalysisData(this.period);
}
public onSymbolChartClicked({ dataSource, symbol }: UniqueAsset) { public onSymbolChartClicked({ dataSource, symbol }: UniqueAsset) {
if (dataSource && symbol) { if (dataSource && symbol) {
this.router.navigate([], { this.router.navigate([], {

48
apps/client/src/app/pages/portfolio/allocations/allocations-page.html

@ -39,12 +39,6 @@
<mat-card class="mb-3"> <mat-card class="mb-3">
<mat-card-header class="overflow-hidden w-100"> <mat-card-header class="overflow-hidden w-100">
<mat-card-title class="text-truncate" i18n>By Account</mat-card-title> <mat-card-title class="text-truncate" i18n>By Account</mat-card-title>
<gf-toggle
[defaultValue]="period"
[isLoading]="false"
[options]="periodOptions"
(change)="onChangePeriod($event.value)"
></gf-toggle>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<gf-portfolio-proportion-chart <gf-portfolio-proportion-chart
@ -70,12 +64,6 @@
class="ml-1" class="ml-1"
></gf-premium-indicator ></gf-premium-indicator
></mat-card-title> ></mat-card-title>
<gf-toggle
[defaultValue]="period"
[isLoading]="false"
[options]="periodOptions"
(change)="onChangePeriod($event.value)"
></gf-toggle>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<gf-portfolio-proportion-chart <gf-portfolio-proportion-chart
@ -99,12 +87,6 @@
class="ml-1" class="ml-1"
></gf-premium-indicator ></gf-premium-indicator
></mat-card-title> ></mat-card-title>
<gf-toggle
[defaultValue]="period"
[isLoading]="false"
[options]="periodOptions"
(change)="onChangePeriod($event.value)"
></gf-toggle>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<gf-portfolio-proportion-chart <gf-portfolio-proportion-chart
@ -124,12 +106,6 @@
<mat-card-title class="align-items-center d-flex text-truncate"> <mat-card-title class="align-items-center d-flex text-truncate">
<ng-container i18n>By Holding</ng-container></mat-card-title <ng-container i18n>By Holding</ng-container></mat-card-title
> >
<gf-toggle
[defaultValue]="period"
[isLoading]="false"
[options]="periodOptions"
(change)="onChangePeriod($event.value)"
></gf-toggle>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<gf-portfolio-proportion-chart <gf-portfolio-proportion-chart
@ -157,12 +133,6 @@
class="ml-1" class="ml-1"
></gf-premium-indicator ></gf-premium-indicator
></mat-card-title> ></mat-card-title>
<gf-toggle
[defaultValue]="period"
[isLoading]="false"
[options]="periodOptions"
(change)="onChangePeriod($event.value)"
></gf-toggle>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<gf-portfolio-proportion-chart <gf-portfolio-proportion-chart
@ -187,12 +157,6 @@
class="ml-1" class="ml-1"
></gf-premium-indicator ></gf-premium-indicator
></mat-card-title> ></mat-card-title>
<gf-toggle
[defaultValue]="period"
[isLoading]="false"
[options]="periodOptions"
(change)="onChangePeriod($event.value)"
></gf-toggle>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<gf-portfolio-proportion-chart <gf-portfolio-proportion-chart
@ -216,12 +180,6 @@
class="ml-1" class="ml-1"
></gf-premium-indicator ></gf-premium-indicator
></mat-card-title> ></mat-card-title>
<gf-toggle
[defaultValue]="period"
[isLoading]="false"
[options]="periodOptions"
(change)="onChangePeriod($event.value)"
></gf-toggle>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<gf-portfolio-proportion-chart <gf-portfolio-proportion-chart
@ -248,12 +206,6 @@
class="ml-1" class="ml-1"
></gf-premium-indicator ></gf-premium-indicator
></mat-card-title> ></mat-card-title>
<gf-toggle
[defaultValue]="period"
[isLoading]="false"
[options]="periodOptions"
(change)="onChangePeriod($event.value)"
></gf-toggle>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<gf-world-map-chart <gf-world-map-chart

2
apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts

@ -3,7 +3,6 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatDialogModule } from '@angular/material/dialog'; import { MatDialogModule } from '@angular/material/dialog';
import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatProgressBarModule } from '@angular/material/progress-bar';
import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module';
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module'; import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module';
import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module'; import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module';
@ -21,7 +20,6 @@ import { AllocationsPageComponent } from './allocations-page.component';
GfActivitiesFilterModule, GfActivitiesFilterModule,
GfPortfolioProportionChartModule, GfPortfolioProportionChartModule,
GfPremiumIndicatorModule, GfPremiumIndicatorModule,
GfToggleModule,
GfWorldMapChartModule, GfWorldMapChartModule,
GfValueModule, GfValueModule,
MatCardModule, MatCardModule,

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

@ -131,7 +131,7 @@ export class PublicPageComponent implements OnInit {
for (const [symbol, position] of Object.entries( for (const [symbol, position] of Object.entries(
this.portfolioPublicDetails.holdings this.portfolioPublicDetails.holdings
)) { )) {
const value = position.allocationCurrent; const value = position.allocationInPercentage;
this.positions[symbol] = { this.positions[symbol] = {
value, value,

3
libs/common/src/lib/interfaces/portfolio-position.interface.ts

@ -5,8 +5,7 @@ import { Country } from './country.interface';
import { Sector } from './sector.interface'; import { Sector } from './sector.interface';
export interface PortfolioPosition { export interface PortfolioPosition {
allocationCurrent: number; allocationInPercentage: number;
allocationInvestment: number;
assetClass?: AssetClass; assetClass?: AssetClass;
assetSubClass?: AssetSubClass | 'CASH'; assetSubClass?: AssetSubClass | 'CASH';
countries: Country[]; countries: Country[];

2
libs/common/src/lib/interfaces/portfolio-public-details.interface.ts

@ -6,7 +6,7 @@ export interface PortfolioPublicDetails {
holdings: { holdings: {
[symbol: string]: Pick< [symbol: string]: Pick<
PortfolioPosition, PortfolioPosition,
| 'allocationCurrent' | 'allocationInPercentage'
| 'countries' | 'countries'
| 'currency' | 'currency'
| 'dataSource' | 'dataSource'

6
libs/ui/src/lib/holdings-table/holdings-table.component.html

@ -3,7 +3,7 @@
class="gf-table w-100" class="gf-table w-100"
mat-table mat-table
matSort matSort
matSortActive="allocationCurrent" matSortActive="allocationInPercentage"
matSortDirection="desc" matSortDirection="desc"
[dataSource]="dataSource" [dataSource]="dataSource"
> >
@ -85,7 +85,7 @@
</td> </td>
</ng-container> </ng-container>
<ng-container matColumnDef="allocationCurrent"> <ng-container matColumnDef="allocationInPercentage">
<th <th
*matHeaderCellDef *matHeaderCellDef
class="justify-content-end px-1" class="justify-content-end px-1"
@ -99,7 +99,7 @@
<gf-value <gf-value
[isPercent]="true" [isPercent]="true"
[locale]="locale" [locale]="locale"
[value]="isLoading ? undefined : element.allocationCurrent" [value]="isLoading ? undefined : element.allocationInPercentage"
></gf-value> ></gf-value>
</div> </div>
</td> </td>

2
libs/ui/src/lib/holdings-table/holdings-table.component.ts

@ -58,7 +58,7 @@ export class HoldingsTableComponent implements OnChanges, OnDestroy, OnInit {
this.displayedColumns.push('value'); this.displayedColumns.push('value');
} }
this.displayedColumns.push('allocationCurrent'); this.displayedColumns.push('allocationInPercentage');
this.displayedColumns.push('performance'); this.displayedColumns.push('performance');
this.isLoading = true; this.isLoading = true;

Loading…
Cancel
Save