Browse Source

Refactor portfolio service

pull/5063/head
Thomas Kaul 2 days ago
parent
commit
71d8e969b1
  1. 3
      apps/api/src/app/import/import.controller.ts
  2. 12
      apps/api/src/app/import/import.service.ts
  3. 36
      apps/api/src/app/portfolio/portfolio.controller.ts
  4. 66
      apps/api/src/app/portfolio/portfolio.service.ts

3
apps/api/src/app/import/import.controller.ts

@ -100,7 +100,8 @@ export class ImportController {
): Promise<ImportResponse> { ): Promise<ImportResponse> {
const activities = await this.importService.getDividends({ const activities = await this.importService.getDividends({
dataSource, dataSource,
symbol symbol,
userId: this.request.user.id
}); });
return { activities }; return { activities };

12
apps/api/src/app/import/import.service.ts

@ -48,11 +48,17 @@ export class ImportService {
public async getDividends({ public async getDividends({
dataSource, dataSource,
symbol symbol,
}: AssetProfileIdentifier): Promise<Activity[]> { userId
}: AssetProfileIdentifier & { userId: string }): Promise<Activity[]> {
try { try {
const { activities, firstBuyDate, historicalData } = const { activities, firstBuyDate, historicalData } =
await this.portfolioService.getHolding(dataSource, undefined, symbol); await this.portfolioService.getHolding({
dataSource,
symbol,
userId,
impersonationId: undefined
});
const [[assetProfile], dividends] = await Promise.all([ const [[assetProfile], dividends] = await Promise.all([
this.symbolProfileService.getSymbolProfiles([ this.symbolProfileService.getSymbolProfiles([

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

@ -375,11 +375,12 @@ export class PortfolioController {
@Param('dataSource') dataSource: DataSource, @Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string @Param('symbol') symbol: string
): Promise<PortfolioHoldingResponse> { ): Promise<PortfolioHoldingResponse> {
const holding = await this.portfolioService.getHolding( const holding = await this.portfolioService.getHolding({
dataSource, dataSource,
impersonationId, impersonationId,
symbol symbol,
); userId: this.request.user.id
});
if (!holding) { if (!holding) {
throw new HttpException( throw new HttpException(
@ -453,7 +454,8 @@ export class PortfolioController {
filters, filters,
groupBy, groupBy,
impersonationId, impersonationId,
savingsRate: this.request.user?.Settings?.settings.savingsRate savingsRate: this.request.user?.Settings?.settings.savingsRate,
userId: this.request.user.id
}); });
if ( if (
@ -622,11 +624,12 @@ export class PortfolioController {
@Param('dataSource') dataSource: DataSource, @Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string @Param('symbol') symbol: string
): Promise<PortfolioHoldingResponse> { ): Promise<PortfolioHoldingResponse> {
const holding = await this.portfolioService.getHolding( const holding = await this.portfolioService.getHolding({
dataSource, dataSource,
impersonationId, impersonationId,
symbol symbol,
); userId: this.request.user.id
});
if (!holding) { if (!holding) {
throw new HttpException( throw new HttpException(
@ -643,7 +646,10 @@ export class PortfolioController {
public async getReport( public async getReport(
@Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string
): Promise<PortfolioReportResponse> { ): Promise<PortfolioReportResponse> {
const report = await this.portfolioService.getReport(impersonationId); const report = await this.portfolioService.getReport({
impersonationId,
userId: this.request.user.id
});
if ( if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
@ -672,11 +678,12 @@ export class PortfolioController {
@Param('dataSource') dataSource: DataSource, @Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string @Param('symbol') symbol: string
): Promise<void> { ): Promise<void> {
const holding = await this.portfolioService.getHolding( const holding = await this.portfolioService.getHolding({
dataSource, dataSource,
impersonationId, impersonationId,
symbol symbol,
); userId: this.request.user.id
});
if (!holding) { if (!holding) {
throw new HttpException( throw new HttpException(
@ -707,11 +714,12 @@ export class PortfolioController {
@Param('dataSource') dataSource: DataSource, @Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string @Param('symbol') symbol: string
): Promise<void> { ): Promise<void> {
const holding = await this.portfolioService.getHolding( const holding = await this.portfolioService.getHolding({
dataSource, dataSource,
impersonationId, impersonationId,
symbol symbol,
); userId: this.request.user.id
});
if (!holding) { if (!holding) {
throw new HttpException( throw new HttpException(

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

@ -274,15 +274,17 @@ export class PortfolioService {
filters, filters,
groupBy, groupBy,
impersonationId, impersonationId,
savingsRate savingsRate,
userId
}: { }: {
dateRange: DateRange; dateRange: DateRange;
filters?: Filter[]; filters?: Filter[];
groupBy?: GroupBy; groupBy?: GroupBy;
impersonationId: string; impersonationId: string;
savingsRate: number; savingsRate: number;
userId: string;
}): Promise<PortfolioInvestments> { }): Promise<PortfolioInvestments> {
const userId = await this.getUserId(impersonationId, this.request.user.id); userId = await this.getUserId(impersonationId, userId);
const user = await this.userService.user({ id: userId }); const user = await this.userService.user({ id: userId });
const userCurrency = this.getUserCurrency(user); const userCurrency = this.getUserCurrency(user);
@ -638,12 +640,18 @@ export class PortfolioService {
}; };
} }
public async getHolding( public async getHolding({
aDataSource: DataSource, dataSource,
aImpersonationId: string, impersonationId,
aSymbol: string symbol,
): Promise<PortfolioHoldingResponse> { userId
const userId = await this.getUserId(aImpersonationId, this.request.user.id); }: {
dataSource: DataSource;
impersonationId: string;
symbol: string;
userId: string;
}): Promise<PortfolioHoldingResponse> {
userId = await this.getUserId(impersonationId, userId);
const user = await this.userService.user({ id: userId }); const user = await this.userService.user({ id: userId });
const userCurrency = this.getUserCurrency(user); const userCurrency = this.getUserCurrency(user);
@ -686,7 +694,7 @@ export class PortfolioService {
} }
const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([ const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([
{ dataSource: aDataSource, symbol: aSymbol } { dataSource, symbol }
]); ]);
const portfolioCalculator = this.calculatorFactory.createCalculator({ const portfolioCalculator = this.calculatorFactory.createCalculator({
@ -701,8 +709,8 @@ export class PortfolioService {
const { positions } = await portfolioCalculator.getSnapshot(); const { positions } = await portfolioCalculator.getSnapshot();
const position = positions.find(({ dataSource, symbol }) => { const position = positions.find((position) => {
return dataSource === aDataSource && symbol === aSymbol; return position.dataSource === dataSource && position.symbol === symbol;
}); });
if (position) { if (position) {
@ -749,7 +757,7 @@ export class PortfolioService {
}); });
const historicalData = await this.dataProviderService.getHistorical( const historicalData = await this.dataProviderService.getHistorical(
[{ dataSource, symbol: aSymbol }], [{ dataSource, symbol }],
'day', 'day',
parseISO(firstBuyDate), parseISO(firstBuyDate),
new Date() new Date()
@ -769,10 +777,10 @@ export class PortfolioService {
marketPrice marketPrice
); );
if (historicalData[aSymbol]) { if (historicalData[symbol]) {
let j = -1; let j = -1;
for (const [date, { marketPrice }] of Object.entries( for (const [date, { marketPrice }] of Object.entries(
historicalData[aSymbol] historicalData[symbol]
)) { )) {
while ( while (
j + 1 < transactionPoints.length && j + 1 < transactionPoints.length &&
@ -785,8 +793,8 @@ export class PortfolioService {
let currentQuantity = 0; let currentQuantity = 0;
const currentSymbol = transactionPoints[j]?.items.find( const currentSymbol = transactionPoints[j]?.items.find(
({ symbol }) => { (transactionPointSymbol) => {
return symbol === aSymbol; return transactionPointSymbol.symbol === symbol;
} }
); );
@ -884,12 +892,12 @@ export class PortfolioService {
} else { } else {
const currentData = await this.dataProviderService.getQuotes({ const currentData = await this.dataProviderService.getQuotes({
user, user,
items: [{ dataSource: DataSource.YAHOO, symbol: aSymbol }] items: [{ symbol, dataSource: DataSource.YAHOO }]
}); });
const marketPrice = currentData[aSymbol]?.marketPrice; const marketPrice = currentData[symbol]?.marketPrice;
let historicalData = await this.dataProviderService.getHistorical( let historicalData = await this.dataProviderService.getHistorical(
[{ dataSource: DataSource.YAHOO, symbol: aSymbol }], [{ symbol, dataSource: DataSource.YAHOO }],
'day', 'day',
portfolioStart, portfolioStart,
new Date() new Date()
@ -898,15 +906,13 @@ export class PortfolioService {
if (isEmpty(historicalData)) { if (isEmpty(historicalData)) {
try { try {
historicalData = await this.dataProviderService.getHistoricalRaw({ historicalData = await this.dataProviderService.getHistoricalRaw({
assetProfileIdentifiers: [ assetProfileIdentifiers: [{ symbol, dataSource: DataSource.YAHOO }],
{ dataSource: DataSource.YAHOO, symbol: aSymbol }
],
from: portfolioStart, from: portfolioStart,
to: new Date() to: new Date()
}); });
} catch { } catch {
historicalData = { historicalData = {
[aSymbol]: {} [symbol]: {}
}; };
} }
} }
@ -917,7 +923,7 @@ export class PortfolioService {
let marketPriceMin = marketPrice; let marketPriceMin = marketPrice;
for (const [date, { marketPrice }] of Object.entries( for (const [date, { marketPrice }] of Object.entries(
historicalData[aSymbol] historicalData[symbol]
)) { )) {
historicalDataArray.push({ historicalDataArray.push({
date, date,
@ -1227,10 +1233,14 @@ export class PortfolioService {
}; };
} }
public async getReport( public async getReport({
impersonationId: string impersonationId,
): Promise<PortfolioReportResponse> { userId
const userId = await this.getUserId(impersonationId, this.request.user.id); }: {
impersonationId: string;
userId: string;
}): Promise<PortfolioReportResponse> {
userId = await this.getUserId(impersonationId, userId);
const userSettings = this.request.user.Settings.settings as UserSettings; const userSettings = this.request.user.Settings.settings as UserSettings;
const { accounts, holdings, markets, marketsAdvanced, summary } = const { accounts, holdings, markets, marketsAdvanced, summary } =

Loading…
Cancel
Save