Browse Source

Fix creation of asset profiles with symbol in wrong letter case by using original symbol

pull/7727/head
Thomas Kaul 3 days ago
parent
commit
7b262aeeaa
  1. 23
      apps/api/src/app/activities/activities.controller.ts
  2. 27
      apps/api/src/services/symbol-profile/symbol-profile.service.ts
  3. 19
      apps/client/src/app/components/admin-market-data/admin-market-data.component.ts

23
apps/api/src/app/activities/activities.controller.ts

@ -8,6 +8,7 @@ import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interc
import { ApiService } from '@ghostfolio/api/services/api/api.service'; import { ApiService } from '@ghostfolio/api/services/api/api.service';
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper';
import { DATA_GATHERING_QUEUE_PRIORITY_HIGH } from '@ghostfolio/common/config'; import { DATA_GATHERING_QUEUE_PRIORITY_HIGH } from '@ghostfolio/common/config';
import { CreateOrderDto, UpdateOrderDto } from '@ghostfolio/common/dtos'; import { CreateOrderDto, UpdateOrderDto } from '@ghostfolio/common/dtos';
@ -47,7 +48,8 @@ export class ActivitiesController {
private readonly activitiesService: ActivitiesService, private readonly activitiesService: ActivitiesService,
private readonly apiService: ApiService, private readonly apiService: ApiService,
private readonly dataProviderService: DataProviderService, private readonly dataProviderService: DataProviderService,
private readonly dataGatheringService: DataGatheringService private readonly dataGatheringService: DataGatheringService,
private readonly symbolProfileService: SymbolProfileService
) {} ) {}
@Delete() @Delete()
@ -256,10 +258,14 @@ export class ActivitiesController {
const customCurrency = data.customCurrency; const customCurrency = data.customCurrency;
const dataSource = data.dataSource; const dataSource = data.dataSource;
const symbol = const symbol = await this.symbolProfileService.getSymbolOfAssetProfile({
assetProfiles[ dataSource,
getAssetProfileIdentifier({ dataSource, symbol: data.symbol }) symbol: data.symbol,
]?.symbol ?? data.symbol; symbolOfDataProvider:
assetProfiles[
getAssetProfileIdentifier({ dataSource, symbol: data.symbol })
]?.symbol
});
if (customCurrency) { if (customCurrency) {
data.currency = customCurrency; data.currency = customCurrency;
@ -340,6 +346,11 @@ export class ActivitiesController {
const customCurrency = data.customCurrency; const customCurrency = data.customCurrency;
const dataSource = data.dataSource; const dataSource = data.dataSource;
const symbol = await this.symbolProfileService.getSymbolOfAssetProfile({
dataSource,
symbol: data.symbol
});
delete data.accountId; delete data.accountId;
if (customCurrency) { if (customCurrency) {
@ -366,7 +377,7 @@ export class ActivitiesController {
connect: { connect: {
dataSource_symbol: { dataSource_symbol: {
dataSource, dataSource,
symbol: data.symbol symbol
} }
}, },
update: { update: {

27
apps/api/src/services/symbol-profile/symbol-profile.service.ts

@ -126,6 +126,33 @@ export class SymbolProfileService {
}); });
} }
/**
* Gets the symbol to use for an asset profile. An asset profile which is
* already in the database wins, also if its symbol has a different letter
* case. This prevents a second asset profile for the same instrument.
* Otherwise the symbol of the data provider is used, because it has the
* correct letter case. A custom asset profile (MANUAL) belongs to a user,
* thus its symbol stays unchanged.
*/
public async getSymbolOfAssetProfile({
dataSource,
symbol,
symbolOfDataProvider
}: { symbolOfDataProvider?: string } & AssetProfileIdentifier) {
if (dataSource === DataSource.MANUAL) {
return symbol;
}
const symbolProfile = await this.prismaService.symbolProfile.findFirst({
where: {
dataSource,
symbol: { equals: symbol, mode: 'insensitive' }
}
});
return symbolProfile?.symbol ?? symbolOfDataProvider ?? symbol;
}
public async getSymbolProfiles( public async getSymbolProfiles(
aAssetProfileIdentifiers: AssetProfileIdentifier[] aAssetProfileIdentifiers: AssetProfileIdentifier[]
): Promise<EnhancedAssetProfile[]> { ): Promise<EnhancedAssetProfile[]> {

19
apps/client/src/app/components/admin-market-data/admin-market-data.component.ts

@ -496,13 +496,18 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit {
this.adminService this.adminService
.addAssetProfile({ dataSource, symbol }) .addAssetProfile({ dataSource, symbol })
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((assetProfile) => { .subscribe({
this.loadData(); error: () => {
this.router.navigate(['.'], { relativeTo: this.route });
this.onOpenAssetProfileDialog({ },
dataSource, next: (assetProfile) => {
symbol: assetProfile?.symbol ?? symbol this.loadData();
});
this.onOpenAssetProfileDialog({
dataSource,
symbol: assetProfile?.symbol ?? symbol
});
}
}); });
} else { } else {
this.loadData(); this.loadData();

Loading…
Cancel
Save