Feature/extend asset profile for currency (#3495)
* Extend asset profile for currency * Update changelog
This commit is contained in:
parent
70e633b997
commit
ff121243e4
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -146,7 +146,7 @@
|
||||
i18n
|
||||
size="medium"
|
||||
[locale]="data.locale"
|
||||
[value]="assetProfile?.activitiesCount ?? 0"
|
||||
[value]="assetProfile?.activitiesCount"
|
||||
>Activities</gf-value
|
||||
>
|
||||
</div>
|
||||
|
@ -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…
x
Reference in New Issue
Block a user