diff --git a/CHANGELOG.md b/CHANGELOG.md index f3598581f..07b37e80b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Extended the search by `isin` in the _Financial Modeling Prep_ service - Switched to _ESLint_’s flat config format - Upgraded `eslint` dependencies diff --git a/apps/api/src/app/symbol/symbol.controller.ts b/apps/api/src/app/symbol/symbol.controller.ts index 89cdd416c..5d9a49a29 100644 --- a/apps/api/src/app/symbol/symbol.controller.ts +++ b/apps/api/src/app/symbol/symbol.controller.ts @@ -47,7 +47,7 @@ export class SymbolController { try { return this.symbolService.lookup({ includeIndices, - query: query.toLowerCase(), + query, user: this.request.user }); } catch { diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index ed55b3c2f..edde92cbb 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -20,12 +20,13 @@ import { import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; +import { isISIN } from 'class-validator'; import { format, isAfter, isBefore, isSameDay } from 'date-fns'; @Injectable() export class FinancialModelingPrepService implements DataProviderInterface { private apiKey: string; - private readonly URL = 'https://financialmodelingprep.com/api/v3'; + private readonly URL = this.getUrl({ version: 3 }); public constructor( private readonly configurationService: ConfigurationService @@ -161,25 +162,49 @@ export class FinancialModelingPrepService implements DataProviderInterface { let items: LookupItem[] = []; try { - const result = await fetch( - `${this.URL}/search?query=${query}&apikey=${this.apiKey}`, - { - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) - } - ).then((res) => res.json()); - - items = result.map(({ currency, name, symbol }) => { - return { - // TODO: Add assetClass - // TODO: Add assetSubClass - currency, - name, - symbol, - dataSource: this.getName() - }; - }); + if (isISIN(query)) { + const result = await fetch( + `${this.getUrl({ version: 4 })}/search/isin?isin=${query}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout( + this.configurationService.get('REQUEST_TIMEOUT') + ) + } + ).then((res) => res.json()); + + items = result.map(({ companyName, currency, symbol }) => { + return { + currency, + symbol, + assetClass: undefined, // TODO + assetSubClass: undefined, // TODO + dataProviderInfo: this.getDataProviderInfo(), + dataSource: this.getName(), + name: companyName + }; + }); + } else { + const result = await fetch( + `${this.URL}/search?query=${query}&apikey=${this.apiKey}`, + { + signal: AbortSignal.timeout( + this.configurationService.get('REQUEST_TIMEOUT') + ) + } + ).then((res) => res.json()); + + items = result.map(({ currency, name, symbol }) => { + return { + currency, + name, + symbol, + assetClass: undefined, // TODO + assetSubClass: undefined, // TODO + dataProviderInfo: this.getDataProviderInfo(), + dataSource: this.getName() + }; + }); + } } catch (error) { let message = error; @@ -194,4 +219,8 @@ export class FinancialModelingPrepService implements DataProviderInterface { return { items }; } + + private getUrl({ version }: { version: number }) { + return `https://financialmodelingprep.com/api/v${version}`; + } }