Feature/improve portfolio details endpoint (#302)

* Make details endpoint fault tolerant (do not throw error)

* Update changelog
pull/303/head
Thomas Kaul 3 years ago committed by GitHub
parent c71a4c078e
commit c2ab6a6c44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
### Changed
- Improved the fault tolerance of the portfolio details endpoint
### Fixed ### Fixed
- Fixed the node engine version mismatch in `package.json` - Fixed the node engine version mismatch in `package.json`

@ -125,17 +125,12 @@ export class PortfolioController {
@Query('range') range, @Query('range') range,
@Res() res: Response @Res() res: Response
): Promise<{ [symbol: string]: PortfolioPosition }> { ): Promise<{ [symbol: string]: PortfolioPosition }> {
let details: { [symbol: string]: PortfolioPosition } = {}; const { details, hasErrors } = await this.portfolioService.getDetails(
impersonationId,
try { range
details = await this.portfolioService.getDetails(impersonationId, range); );
} catch (error) {
console.error(error);
res.status(StatusCodes.ACCEPTED);
}
if (hasNotDefinedValuesInObject(details)) { if (hasErrors || hasNotDefinedValuesInObject(details)) {
res.status(StatusCodes.ACCEPTED); res.status(StatusCodes.ACCEPTED);
} }

@ -154,7 +154,10 @@ export class PortfolioService {
public async getDetails( public async getDetails(
aImpersonationId: string, aImpersonationId: string,
aDateRange: DateRange = 'max' aDateRange: DateRange = 'max'
): Promise<{ [symbol: string]: PortfolioPosition }> { ): Promise<{
details: { [symbol: string]: PortfolioPosition };
hasErrors: boolean;
}> {
const userId = await this.getUserId(aImpersonationId); const userId = await this.getUserId(aImpersonationId);
const userCurrency = this.request.user.Settings.currency; const userCurrency = this.request.user.Settings.currency;
@ -168,7 +171,7 @@ export class PortfolioService {
}); });
if (transactionPoints?.length <= 0) { if (transactionPoints?.length <= 0) {
return {}; return { details: {}, hasErrors: false };
} }
portfolioCalculator.setTransactionPoints(transactionPoints); portfolioCalculator.setTransactionPoints(transactionPoints);
@ -179,16 +182,12 @@ export class PortfolioService {
startDate startDate
); );
if (currentPositions.hasErrors) {
throw new Error('Missing information');
}
const cashDetails = await this.accountService.getCashDetails( const cashDetails = await this.accountService.getCashDetails(
userId, userId,
userCurrency userCurrency
); );
const result: { [symbol: string]: PortfolioPosition } = {}; const details: { [symbol: string]: PortfolioPosition } = {};
const totalInvestment = currentPositions.totalInvestment.plus( const totalInvestment = currentPositions.totalInvestment.plus(
cashDetails.balance cashDetails.balance
); );
@ -218,7 +217,7 @@ export class PortfolioService {
const value = item.quantity.mul(item.marketPrice); const value = item.quantity.mul(item.marketPrice);
const symbolProfile = symbolProfileMap[item.symbol]; const symbolProfile = symbolProfileMap[item.symbol];
const dataProviderResponse = dataProviderResponses[item.symbol]; const dataProviderResponse = dataProviderResponses[item.symbol];
result[item.symbol] = { details[item.symbol] = {
accounts, accounts,
allocationCurrent: value.div(totalValue).toNumber(), allocationCurrent: value.div(totalValue).toNumber(),
allocationInvestment: item.investment.div(totalInvestment).toNumber(), allocationInvestment: item.investment.div(totalInvestment).toNumber(),
@ -226,8 +225,9 @@ export class PortfolioService {
countries: symbolProfile.countries, countries: symbolProfile.countries,
currency: item.currency, currency: item.currency,
exchange: dataProviderResponse.exchange, exchange: dataProviderResponse.exchange,
grossPerformance: item.grossPerformance.toNumber(), grossPerformance: item.grossPerformance?.toNumber() ?? 0,
grossPerformancePercent: item.grossPerformancePercentage.toNumber(), grossPerformancePercent:
item.grossPerformancePercentage?.toNumber() ?? 0,
investment: item.investment.toNumber(), investment: item.investment.toNumber(),
marketPrice: item.marketPrice, marketPrice: item.marketPrice,
marketState: dataProviderResponse.marketState, marketState: dataProviderResponse.marketState,
@ -241,13 +241,13 @@ export class PortfolioService {
} }
// TODO: Add a cash position for each currency // TODO: Add a cash position for each currency
result[ghostfolioCashSymbol] = await this.getCashPosition({ details[ghostfolioCashSymbol] = await this.getCashPosition({
cashDetails, cashDetails,
investment: totalInvestment, investment: totalInvestment,
value: totalValue value: totalValue
}); });
return result; return { details, hasErrors: currentPositions.hasErrors };
} }
public async getPosition( public async getPosition(

Loading…
Cancel
Save