2021-08-01 09:41:44 +02:00
|
|
|
import { EnhancedSymbolProfile } from '@ghostfolio/api/services/interfaces/symbol-profile.interface';
|
2021-07-31 20:45:12 +02:00
|
|
|
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
|
|
|
import { UNKNOWN_KEY } from '@ghostfolio/common/config';
|
|
|
|
import { Country } from '@ghostfolio/common/interfaces/country.interface';
|
|
|
|
import { Sector } from '@ghostfolio/common/interfaces/sector.interface';
|
2021-08-01 09:41:44 +02:00
|
|
|
import { Injectable } from '@nestjs/common';
|
2022-04-22 21:27:55 +02:00
|
|
|
import {
|
|
|
|
DataSource,
|
|
|
|
Prisma,
|
|
|
|
SymbolProfile,
|
|
|
|
SymbolProfileOverrides
|
|
|
|
} from '@prisma/client';
|
2021-08-01 09:41:44 +02:00
|
|
|
import { continents, countries } from 'countries-list';
|
2021-07-31 20:45:12 +02:00
|
|
|
|
2021-11-07 18:36:28 +01:00
|
|
|
import { ScraperConfiguration } from './data-provider/ghostfolio-scraper-api/interfaces/scraper-configuration.interface';
|
|
|
|
|
2021-07-31 20:45:12 +02:00
|
|
|
@Injectable()
|
|
|
|
export class SymbolProfileService {
|
2022-02-03 20:56:39 +01:00
|
|
|
public constructor(private readonly prismaService: PrismaService) {}
|
|
|
|
|
|
|
|
public async delete({
|
|
|
|
dataSource,
|
|
|
|
symbol
|
|
|
|
}: {
|
|
|
|
dataSource: DataSource;
|
|
|
|
symbol: string;
|
|
|
|
}) {
|
|
|
|
return this.prismaService.symbolProfile.delete({
|
|
|
|
where: { dataSource_symbol: { dataSource, symbol } }
|
|
|
|
});
|
|
|
|
}
|
2021-07-31 20:45:12 +02:00
|
|
|
|
2022-02-10 09:39:10 +01:00
|
|
|
public async deleteById(id: string) {
|
|
|
|
return this.prismaService.symbolProfile.delete({
|
|
|
|
where: { id }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-07-31 20:45:12 +02:00
|
|
|
public async getSymbolProfiles(
|
|
|
|
symbols: string[]
|
|
|
|
): Promise<EnhancedSymbolProfile[]> {
|
2021-08-07 22:38:07 +02:00
|
|
|
return this.prismaService.symbolProfile
|
2021-07-31 20:45:12 +02:00
|
|
|
.findMany({
|
2022-04-22 21:27:55 +02:00
|
|
|
include: { SymbolProfileOverrides: true },
|
2021-07-31 20:45:12 +02:00
|
|
|
where: {
|
|
|
|
symbol: {
|
|
|
|
in: symbols
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then((symbolProfiles) => this.getSymbols(symbolProfiles));
|
|
|
|
}
|
|
|
|
|
2022-04-22 21:27:55 +02:00
|
|
|
private getSymbols(
|
|
|
|
symbolProfiles: (SymbolProfile & {
|
|
|
|
SymbolProfileOverrides: SymbolProfileOverrides;
|
|
|
|
})[]
|
|
|
|
): EnhancedSymbolProfile[] {
|
|
|
|
return symbolProfiles.map((symbolProfile) => {
|
|
|
|
const item = {
|
|
|
|
...symbolProfile,
|
|
|
|
countries: this.getCountries(symbolProfile),
|
|
|
|
scraperConfiguration: this.getScraperConfiguration(symbolProfile),
|
|
|
|
sectors: this.getSectors(symbolProfile),
|
|
|
|
symbolMapping: this.getSymbolMapping(symbolProfile)
|
|
|
|
};
|
|
|
|
|
|
|
|
if (item.SymbolProfileOverrides) {
|
|
|
|
item.assetClass =
|
|
|
|
item.SymbolProfileOverrides.assetClass ?? item.assetClass;
|
|
|
|
item.assetSubClass =
|
|
|
|
item.SymbolProfileOverrides.assetSubClass ?? item.assetSubClass;
|
|
|
|
item.countries =
|
2022-05-20 20:16:23 +02:00
|
|
|
(item.SymbolProfileOverrides.countries as unknown as Country[]) ??
|
2022-04-22 21:27:55 +02:00
|
|
|
item.countries;
|
|
|
|
item.name = item.SymbolProfileOverrides?.name ?? item.name;
|
|
|
|
item.sectors =
|
|
|
|
(item.SymbolProfileOverrides.sectors as unknown as Sector[]) ??
|
|
|
|
item.sectors;
|
|
|
|
|
|
|
|
delete item.SymbolProfileOverrides;
|
|
|
|
}
|
|
|
|
|
|
|
|
return item;
|
|
|
|
});
|
2021-07-31 20:45:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private getCountries(symbolProfile: SymbolProfile): Country[] {
|
|
|
|
return ((symbolProfile?.countries as Prisma.JsonArray) ?? []).map(
|
|
|
|
(country) => {
|
|
|
|
const { code, weight } = country as Prisma.JsonObject;
|
|
|
|
|
|
|
|
return {
|
|
|
|
code: code as string,
|
|
|
|
continent:
|
|
|
|
continents[countries[code as string]?.continent] ?? UNKNOWN_KEY,
|
|
|
|
name: countries[code as string]?.name ?? UNKNOWN_KEY,
|
|
|
|
weight: weight as number
|
|
|
|
};
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-11-07 18:36:28 +01:00
|
|
|
private getScraperConfiguration(
|
|
|
|
symbolProfile: SymbolProfile
|
|
|
|
): ScraperConfiguration {
|
|
|
|
const scraperConfiguration =
|
|
|
|
symbolProfile.scraperConfiguration as Prisma.JsonObject;
|
|
|
|
|
2021-11-07 21:25:18 +01:00
|
|
|
if (scraperConfiguration) {
|
|
|
|
return {
|
2022-03-19 12:17:28 +01:00
|
|
|
defaultMarketPrice: scraperConfiguration.defaultMarketPrice as number,
|
2021-11-07 21:25:18 +01:00
|
|
|
selector: scraperConfiguration.selector as string,
|
|
|
|
url: scraperConfiguration.url as string
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2021-11-07 18:36:28 +01:00
|
|
|
}
|
|
|
|
|
2021-07-31 20:45:12 +02:00
|
|
|
private getSectors(symbolProfile: SymbolProfile): Sector[] {
|
|
|
|
return ((symbolProfile?.sectors as Prisma.JsonArray) ?? []).map(
|
|
|
|
(sector) => {
|
|
|
|
const { name, weight } = sector as Prisma.JsonObject;
|
|
|
|
|
|
|
|
return {
|
|
|
|
name: (name as string) ?? UNKNOWN_KEY,
|
|
|
|
weight: weight as number
|
|
|
|
};
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2021-11-07 09:42:36 +01:00
|
|
|
|
|
|
|
private getSymbolMapping(symbolProfile: SymbolProfile) {
|
|
|
|
return (
|
|
|
|
(symbolProfile['symbolMapping'] as {
|
|
|
|
[key: string]: string;
|
|
|
|
}) ?? {}
|
|
|
|
);
|
|
|
|
}
|
2021-07-31 20:45:12 +02:00
|
|
|
}
|