Browse Source

Feature/extend asset profile for currency (#3495)

* Extend asset profile for currency

* Update changelog
pull/3508/head
Eduardo Marinho 4 months ago
committed by GitHub
parent
commit
ff121243e4
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 2
      apps/api/src/app/admin/admin.module.ts
  3. 43
      apps/api/src/app/admin/admin.service.ts
  4. 26
      apps/api/src/app/order/order.service.ts
  5. 2
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
  6. 25
      libs/common/src/lib/helper.ts

1
CHANGELOG.md

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added a dialog for the benchmarks in the markets overview
- Extended the asset profile details dialog of the admin control for currencies
- Extended the content of the _Self-Hosting_ section by the mobile app question on the Frequently Asked Questions (FAQ) page
### Changed

2
apps/api/src/app/admin/admin.module.ts

@ -1,3 +1,4 @@
import { OrderModule } from '@ghostfolio/api/app/order/order.module';
import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module';
import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module';
import { ApiModule } from '@ghostfolio/api/services/api/api.module';
@ -24,6 +25,7 @@ import { QueueModule } from './queue/queue.module';
DataProviderModule,
ExchangeRateDataModule,
MarketDataModule,
OrderModule,
PrismaModule,
PropertyModule,
QueueModule,

43
apps/api/src/app/admin/admin.service.ts

@ -1,3 +1,4 @@
import { OrderService } from '@ghostfolio/api/app/order/order.service';
import { SubscriptionService } from '@ghostfolio/api/app/subscription/subscription.service';
import { environment } from '@ghostfolio/api/environments/environment';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
@ -13,11 +14,13 @@ import {
PROPERTY_IS_READ_ONLY_MODE,
PROPERTY_IS_USER_SIGNUP_ENABLED
} from '@ghostfolio/common/config';
import { isCurrency, getCurrencyFromSymbol } from '@ghostfolio/common/helper';
import {
AdminData,
AdminMarketData,
AdminMarketDataDetails,
AdminMarketDataItem,
EnhancedSymbolProfile,
Filter,
UniqueAsset
} from '@ghostfolio/common/interfaces';
@ -42,6 +45,7 @@ export class AdminService {
private readonly dataProviderService: DataProviderService,
private readonly exchangeRateDataService: ExchangeRateDataService,
private readonly marketDataService: MarketDataService,
private readonly orderService: OrderService,
private readonly prismaService: PrismaService,
private readonly propertyService: PropertyService,
private readonly subscriptionService: SubscriptionService,
@ -295,6 +299,16 @@ export class AdminService {
dataSource,
symbol
}: UniqueAsset): Promise<AdminMarketDataDetails> {
let activitiesCount: EnhancedSymbolProfile['activitiesCount'] = 0;
let currency: EnhancedSymbolProfile['currency'] = '-';
let dateOfFirstActivity: EnhancedSymbolProfile['dateOfFirstActivity'];
if (isCurrency(getCurrencyFromSymbol(symbol))) {
currency = getCurrencyFromSymbol(symbol);
({ activitiesCount, dateOfFirstActivity } =
await this.orderService.getStatisticsByCurrency(currency));
}
const [[assetProfile], marketData] = await Promise.all([
this.symbolProfileService.getSymbolProfiles([
{
@ -322,8 +336,11 @@ export class AdminService {
return {
marketData,
assetProfile: assetProfile ?? {
symbol,
currency: '-'
activitiesCount,
currency,
dataSource,
dateOfFirstActivity,
symbol
}
};
}
@ -413,19 +430,15 @@ export class AdminService {
this.exchangeRateDataService
.getCurrencyPairs()
.map(async ({ dataSource, symbol }) => {
const currency = symbol.replace(DEFAULT_CURRENCY, '');
let activitiesCount: EnhancedSymbolProfile['activitiesCount'] = 0;
let currency: EnhancedSymbolProfile['currency'] = '-';
let dateOfFirstActivity: EnhancedSymbolProfile['dateOfFirstActivity'];
const { _count, _min } = await this.prismaService.order.aggregate({
_count: true,
_min: {
date: true
},
where: {
SymbolProfile: {
currency
}
if (isCurrency(getCurrencyFromSymbol(symbol))) {
currency = getCurrencyFromSymbol(symbol);
({ activitiesCount, dateOfFirstActivity } =
await this.orderService.getStatisticsByCurrency(currency));
}
});
const marketDataItemCount =
marketDataItems.find((marketDataItem) => {
@ -436,15 +449,15 @@ export class AdminService {
})?._count ?? 0;
return {
activitiesCount,
currency,
dataSource,
marketDataItemCount,
symbol,
activitiesCount: _count as number,
assetClass: AssetClass.LIQUIDITY,
assetSubClass: AssetSubClass.CASH,
countriesCount: 0,
date: _min.date,
date: dateOfFirstActivity,
id: undefined,
name: symbol,
sectorsCount: 0

26
apps/api/src/app/order/order.service.ts

@ -10,7 +10,11 @@ import {
GATHER_ASSET_PROFILE_PROCESS_OPTIONS
} from '@ghostfolio/common/config';
import { getAssetProfileIdentifier } from '@ghostfolio/common/helper';
import { Filter, UniqueAsset } from '@ghostfolio/common/interfaces';
import {
EnhancedSymbolProfile,
Filter,
UniqueAsset
} from '@ghostfolio/common/interfaces';
import { OrderWithAccount } from '@ghostfolio/common/types';
import { Injectable } from '@nestjs/common';
@ -429,6 +433,26 @@ export class OrderService {
return { activities, count };
}
public async getStatisticsByCurrency(
currency: EnhancedSymbolProfile['currency']
): Promise<{
activitiesCount: EnhancedSymbolProfile['activitiesCount'];
dateOfFirstActivity: EnhancedSymbolProfile['dateOfFirstActivity'];
}> {
const { _count, _min } = await this.prismaService.order.aggregate({
_count: true,
_min: {
date: true
},
where: { SymbolProfile: { currency } }
});
return {
activitiesCount: _count as number,
dateOfFirstActivity: _min.date
};
}
public async order(
orderWhereUniqueInput: Prisma.OrderWhereUniqueInput
): Promise<Order | null> {

2
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

@ -146,7 +146,7 @@
i18n
size="medium"
[locale]="data.locale"
[value]="assetProfile?.activitiesCount ?? 0"
[value]="assetProfile?.activitiesCount"
>Activities</gf-value
>
</div>

25
libs/common/src/lib/helper.ts

@ -13,7 +13,12 @@ import {
} from 'date-fns';
import { de, es, fr, it, nl, pl, pt, tr, zhCN } from 'date-fns/locale';
import { ghostfolioScraperApiSymbolPrefix, locale } from './config';
import {
DEFAULT_CURRENCY,
DERIVED_CURRENCIES,
ghostfolioScraperApiSymbolPrefix,
locale
} from './config';
import { Benchmark, UniqueAsset } from './interfaces';
import { BenchmarkTrend, ColorScheme } from './types';
@ -161,6 +166,10 @@ export function getCssVariable(aCssVariable: string) {
);
}
export function getCurrencyFromSymbol(aSymbol = '') {
return aSymbol.replace(DEFAULT_CURRENCY, '');
}
export function getDateFnsLocale(aLanguageCode: string) {
if (aLanguageCode === 'de') {
return de;
@ -322,8 +331,18 @@ export function interpolate(template: string, context: any) {
});
}
export function isCurrency(aSymbol = '') {
return currencies[aSymbol];
export function isCurrency(aCurrency = '') {
return currencies[aCurrency] || isDerivedCurrency(aCurrency);
}
export function isDerivedCurrency(aCurrency: string) {
if (aCurrency === 'USX') {
return true;
}
return DERIVED_CURRENCIES.find(({ currency }) => {
return currency === aCurrency;
});
}
export function parseDate(date: string): Date | null {

Loading…
Cancel
Save