Browse Source

Feature/add allocation percentage to accounts table and service

pull/4720/head
Joseph Bao 6 days ago
parent
commit
48e54f27ce
  1. 68
      apps/api/src/app/portfolio/portfolio.service.ts
  2. 37
      apps/client/src/app/components/accounts-table/accounts-table.component.html
  3. 1
      apps/client/src/app/components/accounts-table/accounts-table.component.ts
  4. 1
      libs/common/src/lib/types/account-with-value.type.ts

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

@ -73,6 +73,7 @@ import {
Order, Order,
Platform, Platform,
Prisma, Prisma,
SymbolProfile,
Tag Tag
} from '@prisma/client'; } from '@prisma/client';
import { Big } from 'big.js'; import { Big } from 'big.js';
@ -159,7 +160,11 @@ export class PortfolioService {
this.accountService.accounts({ this.accountService.accounts({
where, where,
include: { include: {
activities: true, activities: {
include: {
SymbolProfile: true
}
},
platform: true platform: true
}, },
orderBy: { name: 'asc' } orderBy: { name: 'asc' }
@ -174,38 +179,71 @@ export class PortfolioService {
const userCurrency = this.request.user.Settings.settings.baseCurrency; const userCurrency = this.request.user.Settings.settings.baseCurrency;
return accounts.map((account) => { const accountsWithValue = accounts.map((account) => {
let transactionCount = 0; let transactionCount = 0;
let valueInBaseCurrency =
details.accounts[account.id]?.valueInBaseCurrency ?? 0;
for (const { isDraft } of account.activities) { if (filterByDataSource && filterBySymbol) {
if (!isDraft) { const holding = details.holdings[filterBySymbol];
transactionCount += 1;
const activities = (
account.activities as (Order & {
SymbolProfile: SymbolProfile;
})[]
).filter((activity) => {
return (
activity.SymbolProfile.dataSource === filterByDataSource &&
activity.SymbolProfile.symbol === filterBySymbol
);
});
let quantity = new Big(0);
for (const activity of activities) {
quantity = quantity.plus(
new Big(getFactor(activity.type)).mul(activity.quantity)
);
} }
}
const valueInBaseCurrency = valueInBaseCurrency = quantity.mul(holding.marketPrice ?? 0).toNumber();
details.accounts[account.id]?.valueInBaseCurrency ?? 0; transactionCount = activities.length;
} else {
for (const { isDraft } of account.activities) {
if (!isDraft) {
transactionCount += 1;
}
}
}
const result = { const result = {
...account, ...account,
transactionCount, allocationInPercentage: 0,
valueInBaseCurrency,
balanceInBaseCurrency: this.exchangeRateDataService.toCurrency( balanceInBaseCurrency: this.exchangeRateDataService.toCurrency(
account.balance, account.balance,
account.currency, account.currency,
userCurrency userCurrency
), ),
transactionCount,
value: this.exchangeRateDataService.toCurrency( value: this.exchangeRateDataService.toCurrency(
valueInBaseCurrency, valueInBaseCurrency,
userCurrency, userCurrency,
account.currency account.currency
) ),
valueInBaseCurrency
}; };
delete result.activities; delete result.activities;
return result; return result;
}); });
if (filterByDataSource && filterBySymbol) {
return accountsWithValue.filter((account) => {
return account.transactionCount > 0;
});
}
return accountsWithValue;
} }
public async getAccountsWithAggregations({ public async getAccountsWithAggregations({
@ -236,6 +274,14 @@ export class PortfolioService {
transactionCount += account.transactionCount; transactionCount += account.transactionCount;
} }
for (const account of accounts) {
account.allocationInPercentage = totalValueInBaseCurrency.gt(0)
? new Big(account.valueInBaseCurrency)
.div(totalValueInBaseCurrency)
.toNumber()
: 0;
}
return { return {
accounts, accounts,
transactionCount, transactionCount,

37
apps/client/src/app/components/accounts-table/accounts-table.component.html

@ -231,6 +231,43 @@
</td> </td>
</ng-container> </ng-container>
<ng-container matColumnDef="allocation">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell justify-content-end px-1"
mat-header-cell
mat-sort-header
>
<ng-container i18n>Allocation</ng-container>
</th>
<td
*matCellDef="let element"
class="d-none d-lg-table-cell px-1 text-right"
mat-cell
>
<gf-value
class="d-inline-block justify-content-end"
[isPercent]="true"
[locale]="locale"
[precision]="2"
[value]="element.allocationInPercentage"
/>
</td>
<td
*matFooterCellDef
class="d-none d-lg-table-cell px-1 text-right"
mat-footer-cell
>
<gf-value
class="d-inline-block justify-content-end"
[isPercent]="true"
[locale]="locale"
[precision]="2"
[value]="1"
/>
</td>
</ng-container>
<ng-container matColumnDef="comment"> <ng-container matColumnDef="comment">
<th <th
*matHeaderCellDef *matHeaderCellDef

1
apps/client/src/app/components/accounts-table/accounts-table.component.ts

@ -81,6 +81,7 @@ export class AccountsTableComponent implements OnChanges, OnDestroy {
this.displayedColumns.push('valueInBaseCurrency'); this.displayedColumns.push('valueInBaseCurrency');
} }
this.displayedColumns.push('allocation');
this.displayedColumns.push('comment'); this.displayedColumns.push('comment');
if (this.showActions) { if (this.showActions) {

1
libs/common/src/lib/types/account-with-value.type.ts

@ -1,6 +1,7 @@
import { Account as AccountModel, Platform } from '@prisma/client'; import { Account as AccountModel, Platform } from '@prisma/client';
export type AccountWithValue = AccountModel & { export type AccountWithValue = AccountModel & {
allocationInPercentage: number;
balanceInBaseCurrency: number; balanceInBaseCurrency: number;
platform?: Platform; platform?: Platform;
transactionCount: number; transactionCount: number;

Loading…
Cancel
Save