Release/1.258.0 (#1878)
* Release 1.258.0 * Introduce data source mapping * Update changelog
This commit is contained in:
parent
ffa020ee2a
commit
5eff8402db
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 1.258.0 - 2023-04-20
|
||||
|
||||
### Added
|
||||
|
||||
- Introduced a data source mapping
|
||||
|
||||
## 1.257.0 - 2023-04-18
|
||||
|
||||
### Added
|
||||
|
@ -6,6 +6,7 @@ import { DataSource, MarketData } from '@prisma/client';
|
||||
|
||||
import { CurrentRateService } from './current-rate.service';
|
||||
import { GetValueObject } from './interfaces/get-value-object.interface';
|
||||
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
|
||||
|
||||
jest.mock('@ghostfolio/api/services/market-data.service', () => {
|
||||
return {
|
||||
@ -67,14 +68,32 @@ jest.mock('@ghostfolio/api/services/exchange-rate-data.service', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@ghostfolio/api/services/property/property.service', () => {
|
||||
return {
|
||||
PropertyService: jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
getByKey: (key: string) => Promise.resolve({})
|
||||
};
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
describe('CurrentRateService', () => {
|
||||
let currentRateService: CurrentRateService;
|
||||
let dataProviderService: DataProviderService;
|
||||
let exchangeRateDataService: ExchangeRateDataService;
|
||||
let marketDataService: MarketDataService;
|
||||
let propertyService: PropertyService;
|
||||
|
||||
beforeAll(async () => {
|
||||
dataProviderService = new DataProviderService(null, [], null);
|
||||
propertyService = new PropertyService(null);
|
||||
|
||||
dataProviderService = new DataProviderService(
|
||||
null,
|
||||
[],
|
||||
null,
|
||||
propertyService
|
||||
);
|
||||
exchangeRateDataService = new ExchangeRateDataService(
|
||||
null,
|
||||
null,
|
||||
|
@ -14,6 +14,7 @@ import { Module } from '@nestjs/common';
|
||||
import { DataEnhancerModule } from './data-enhancer/data-enhancer.module';
|
||||
import { YahooFinanceDataEnhancerService } from './data-enhancer/yahoo-finance/yahoo-finance.service';
|
||||
import { DataProviderService } from './data-provider.service';
|
||||
import { PropertyModule } from '@ghostfolio/api/services/property/property.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -21,6 +22,7 @@ import { DataProviderService } from './data-provider.service';
|
||||
CryptocurrencyModule,
|
||||
DataEnhancerModule,
|
||||
PrismaModule,
|
||||
PropertyModule,
|
||||
SymbolProfileModule
|
||||
],
|
||||
providers: [
|
||||
|
@ -14,15 +14,29 @@ import { Inject, Injectable, Logger } from '@nestjs/common';
|
||||
import { DataSource, MarketData, SymbolProfile } from '@prisma/client';
|
||||
import { format, isValid } from 'date-fns';
|
||||
import { groupBy, isEmpty } from 'lodash';
|
||||
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
|
||||
import { PROPERTY_DATA_SOURCE_MAPPING } from '@ghostfolio/common/config';
|
||||
|
||||
@Injectable()
|
||||
export class DataProviderService {
|
||||
private dataProviderMapping: { [dataProviderName: string]: string };
|
||||
|
||||
public constructor(
|
||||
private readonly configurationService: ConfigurationService,
|
||||
@Inject('DataProviderInterfaces')
|
||||
private readonly dataProviderInterfaces: DataProviderInterface[],
|
||||
private readonly prismaService: PrismaService
|
||||
) {}
|
||||
private readonly prismaService: PrismaService,
|
||||
private readonly propertyService: PropertyService
|
||||
) {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
public async initialize() {
|
||||
this.dataProviderMapping =
|
||||
((await this.propertyService.getByKey(PROPERTY_DATA_SOURCE_MAPPING)) as {
|
||||
[dataProviderName: string]: string;
|
||||
}) ?? {};
|
||||
}
|
||||
|
||||
public async getDividends({
|
||||
dataSource,
|
||||
@ -314,6 +328,21 @@ export class DataProviderService {
|
||||
|
||||
private getDataProvider(providerName: DataSource) {
|
||||
for (const dataProviderInterface of this.dataProviderInterfaces) {
|
||||
if (this.dataProviderMapping[dataProviderInterface.getName()]) {
|
||||
const mappedDataProviderInterface = this.dataProviderInterfaces.find(
|
||||
(currentDataProviderInterface) => {
|
||||
return (
|
||||
currentDataProviderInterface.getName() ===
|
||||
this.dataProviderMapping[dataProviderInterface.getName()]
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
if (mappedDataProviderInterface) {
|
||||
return mappedDataProviderInterface;
|
||||
}
|
||||
}
|
||||
|
||||
if (dataProviderInterface.getName() === providerName) {
|
||||
return dataProviderInterface;
|
||||
}
|
||||
|
@ -146,12 +146,20 @@ export class EodHistoricalDataService implements DataProviderInterface {
|
||||
result: { [symbol: string]: IDataProviderResponse },
|
||||
{ close, code, timestamp }
|
||||
) => {
|
||||
result[code] = {
|
||||
currency: this.convertCurrency(searchResponse?.items[0]?.currency),
|
||||
dataSource: DataSource.EOD_HISTORICAL_DATA,
|
||||
marketPrice: close,
|
||||
marketState: isToday(new Date(timestamp * 1000)) ? 'open' : 'closed'
|
||||
};
|
||||
const currency = this.convertCurrency(
|
||||
searchResponse?.items[0]?.currency
|
||||
);
|
||||
|
||||
if (currency) {
|
||||
result[code] = {
|
||||
currency,
|
||||
dataSource: DataSource.EOD_HISTORICAL_DATA,
|
||||
marketPrice: close,
|
||||
marketState: isToday(new Date(timestamp * 1000))
|
||||
? 'open'
|
||||
: 'closed'
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
@ -62,7 +62,8 @@ export class ExchangeRateDataService {
|
||||
getYesterday()
|
||||
);
|
||||
|
||||
if (Object.keys(result).length !== this.currencyPairs.length) {
|
||||
// TODO: add fallback
|
||||
/*if (Object.keys(result).length !== this.currencyPairs.length) {
|
||||
// Load currencies directly from data provider as a fallback
|
||||
// if historical data is not fully available
|
||||
const historicalData = await this.dataProviderService.getQuotes(
|
||||
@ -72,13 +73,15 @@ export class ExchangeRateDataService {
|
||||
);
|
||||
|
||||
Object.keys(historicalData).forEach((key) => {
|
||||
result[key] = {
|
||||
[format(getYesterday(), DATE_FORMAT)]: {
|
||||
marketPrice: historicalData[key].marketPrice
|
||||
}
|
||||
};
|
||||
if (isNumber(historicalData[key].marketPrice)) {
|
||||
result[key] = {
|
||||
[format(getYesterday(), DATE_FORMAT)]: {
|
||||
marketPrice: historicalData[key].marketPrice
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
}*/
|
||||
|
||||
const resultExtended = result;
|
||||
|
||||
|
@ -73,6 +73,7 @@ export const PROPERTY_BENCHMARKS = 'BENCHMARKS';
|
||||
export const PROPERTY_COUNTRIES_OF_SUBSCRIBERS = 'COUNTRIES_OF_SUBSCRIBERS';
|
||||
export const PROPERTY_COUPONS = 'COUPONS';
|
||||
export const PROPERTY_CURRENCIES = 'CURRENCIES';
|
||||
export const PROPERTY_DATA_SOURCE_MAPPING = 'DATA_SOURCE_MAPPING';
|
||||
export const PROPERTY_DEMO_USER_ID = 'DEMO_USER_ID';
|
||||
export const PROPERTY_IS_READ_ONLY_MODE = 'IS_READ_ONLY_MODE';
|
||||
export const PROPERTY_IS_USER_SIGNUP_ENABLED = 'IS_USER_SIGNUP_ENABLED';
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ghostfolio",
|
||||
"version": "1.257.0",
|
||||
"version": "1.258.0",
|
||||
"homepage": "https://ghostfol.io",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user