Browse Source

Feature/extend accounts endpoint by dividend and interest (#5335)

* Extend accounts endpoint by dividend and interest

* Update changelog
pull/5345/head^2
Attila Cseh 4 days ago
committed by GitHub
parent
commit
711d716de0
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      CHANGELOG.md
  2. 5
      apps/api/src/app/account/account.service.ts
  3. 99
      apps/api/src/app/portfolio/portfolio.service.ts
  4. 3
      apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts
  5. 2
      libs/common/src/lib/interfaces/responses/accounts-response.interface.ts
  6. 2
      libs/common/src/lib/types/account-with-value.type.ts

6
CHANGELOG.md

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Changed
- Extended the accounts endpoint by dividend and interest
## 2.190.0 - 2025-08-09
### Changed

5
apps/api/src/app/account/account.service.ts

@ -12,7 +12,8 @@ import {
AccountBalance,
Order,
Platform,
Prisma
Prisma,
SymbolProfile
} from '@prisma/client';
import { Big } from 'big.js';
import { format } from 'date-fns';
@ -62,7 +63,7 @@ export class AccountService {
orderBy?: Prisma.AccountOrderByWithRelationInput;
}): Promise<
(Account & {
activities?: Order[];
activities?: (Order & { SymbolProfile?: SymbolProfile })[];
balances?: AccountBalance[];
platform?: Platform;
})[]

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

@ -161,7 +161,7 @@ export class PortfolioService {
this.accountService.accounts({
where,
include: {
activities: true,
activities: { include: { SymbolProfile: true } },
platform: true
},
orderBy: { name: 'asc' }
@ -176,39 +176,74 @@ export class PortfolioService {
const userCurrency = this.request.user.settings.settings.baseCurrency;
return accounts.map((account) => {
let transactionCount = 0;
return Promise.all(
accounts.map(async (account) => {
let dividendInBaseCurrency = 0;
let interestInBaseCurrency = 0;
let transactionCount = 0;
for (const { isDraft } of account.activities) {
if (!isDraft) {
transactionCount += 1;
for (const {
currency,
date,
isDraft,
quantity,
SymbolProfile,
type,
unitPrice
} of account.activities) {
switch (type) {
case ActivityType.DIVIDEND:
dividendInBaseCurrency +=
await this.exchangeRateDataService.toCurrencyAtDate(
new Big(quantity).mul(unitPrice).toNumber(),
currency ?? SymbolProfile.currency,
userCurrency,
date
);
break;
case ActivityType.INTEREST:
interestInBaseCurrency +=
await this.exchangeRateDataService.toCurrencyAtDate(
unitPrice,
currency ?? SymbolProfile.currency,
userCurrency,
date
);
break;
}
if (!isDraft) {
transactionCount += 1;
}
}
}
const valueInBaseCurrency =
details.accounts[account.id]?.valueInBaseCurrency ?? 0;
const valueInBaseCurrency =
details.accounts[account.id]?.valueInBaseCurrency ?? 0;
const result = {
...account,
transactionCount,
valueInBaseCurrency,
allocationInPercentage: null, // TODO
balanceInBaseCurrency: this.exchangeRateDataService.toCurrency(
account.balance,
account.currency,
userCurrency
),
value: this.exchangeRateDataService.toCurrency(
const result = {
...account,
dividendInBaseCurrency,
interestInBaseCurrency,
transactionCount,
valueInBaseCurrency,
userCurrency,
account.currency
)
};
allocationInPercentage: null, // TODO
balanceInBaseCurrency: this.exchangeRateDataService.toCurrency(
account.balance,
account.currency,
userCurrency
),
value: this.exchangeRateDataService.toCurrency(
valueInBaseCurrency,
userCurrency,
account.currency
)
};
delete result.activities;
delete result.activities;
return result;
});
return result;
})
);
}
public async getAccountsWithAggregations({
@ -242,6 +277,8 @@ export class PortfolioService {
}
let totalBalanceInBaseCurrency = new Big(0);
let totalDividendInBaseCurrency = new Big(0);
let totalInterestInBaseCurrency = new Big(0);
let totalValueInBaseCurrency = new Big(0);
let transactionCount = 0;
@ -249,6 +286,12 @@ export class PortfolioService {
totalBalanceInBaseCurrency = totalBalanceInBaseCurrency.plus(
account.balanceInBaseCurrency
);
totalDividendInBaseCurrency = totalDividendInBaseCurrency.plus(
account.dividendInBaseCurrency
);
totalInterestInBaseCurrency = totalInterestInBaseCurrency.plus(
account.interestInBaseCurrency
);
totalValueInBaseCurrency = totalValueInBaseCurrency.plus(
account.valueInBaseCurrency
);
@ -259,6 +302,8 @@ export class PortfolioService {
accounts,
transactionCount,
totalBalanceInBaseCurrency: totalBalanceInBaseCurrency.toNumber(),
totalDividendInBaseCurrency: totalDividendInBaseCurrency.toNumber(),
totalInterestInBaseCurrency: totalInterestInBaseCurrency.toNumber(),
totalValueInBaseCurrency: totalValueInBaseCurrency.toNumber()
};
}

3
apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts

@ -50,12 +50,15 @@ export class RedactValuesInResponseInterceptor<T>
'feeInBaseCurrency',
'grossPerformance',
'grossPerformanceWithCurrencyEffect',
'interestInBaseCurrency',
'investment',
'netPerformance',
'netPerformanceWithCurrencyEffect',
'quantity',
'symbolMapping',
'totalBalanceInBaseCurrency',
'totalDividendInBaseCurrency',
'totalInterestInBaseCurrency',
'totalValueInBaseCurrency',
'unitPrice',
'value',

2
libs/common/src/lib/interfaces/responses/accounts-response.interface.ts

@ -3,6 +3,8 @@ import { AccountWithValue } from '@ghostfolio/common/types';
export interface AccountsResponse {
accounts: AccountWithValue[];
totalBalanceInBaseCurrency: number;
totalDividendInBaseCurrency: number;
totalInterestInBaseCurrency: number;
totalValueInBaseCurrency: number;
transactionCount: number;
}

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

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

Loading…
Cancel
Save