From 1b20d1b073319e2814c56a96a15e92786771aaaf Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 28 Jan 2024 18:47:49 +0200 Subject: [PATCH] feat(server): add application layer to exchange rate service --- .../src/api/controllers/ExchangeRates.ts | 8 ++-- .../server/src/interfaces/ExchangeRate.ts | 43 ++++--------------- .../src/lib/ExchangeRate/OpenExchangeRate.ts | 19 ++++++++ .../ExchangeRates/ExchangeRateApplication.ts | 21 +++++++++ .../ExchangeRates/ExchangeRatesService.ts | 13 +----- 5 files changed, 54 insertions(+), 50 deletions(-) create mode 100644 packages/server/src/services/ExchangeRates/ExchangeRateApplication.ts diff --git a/packages/server/src/api/controllers/ExchangeRates.ts b/packages/server/src/api/controllers/ExchangeRates.ts index 4ea59ad1b..5a935a173 100644 --- a/packages/server/src/api/controllers/ExchangeRates.ts +++ b/packages/server/src/api/controllers/ExchangeRates.ts @@ -1,16 +1,16 @@ import { Service, Inject } from 'typedi'; import { Router, Request, Response, NextFunction } from 'express'; -import { check, param, query } from 'express-validator'; +import { query } from 'express-validator'; import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import BaseController from './BaseController'; import { ServiceError } from '@/exceptions'; -import { ExchangeRatesService } from '@/services/ExchangeRates/ExchangeRatesService'; import { EchangeRateErrors } from '@/lib/ExchangeRate/types'; +import { ExchangeRateApplication } from '@/services/ExchangeRates/ExchangeRateApplication'; @Service() export default class ExchangeRatesController extends BaseController { @Inject() - private exchangeRatesService: ExchangeRatesService; + private exchangeRatesApp: ExchangeRateApplication; /** * Constructor method. @@ -43,7 +43,7 @@ export default class ExchangeRatesController extends BaseController { const exchangeRateQuery = this.matchedQueryData(req); try { - const exchangeRate = await this.exchangeRatesService.latest( + const exchangeRate = await this.exchangeRatesApp.latest( tenantId, exchangeRateQuery ); diff --git a/packages/server/src/interfaces/ExchangeRate.ts b/packages/server/src/interfaces/ExchangeRate.ts index fc3bd33e4..757ca5f3d 100644 --- a/packages/server/src/interfaces/ExchangeRate.ts +++ b/packages/server/src/interfaces/ExchangeRate.ts @@ -1,36 +1,9 @@ -import { IFilterRole } from './DynamicFilter'; +export interface ExchangeRateLatestDTO { + toCurrency: string; +} -export interface IExchangeRate { - id: number, - currencyCode: string, - exchangeRate: number, - date: Date, - createdAt: Date, - updatedAt: Date, -}; - -export interface IExchangeRateDTO { - currencyCode: string, - exchangeRate: number, - date: Date, -}; - -export interface IExchangeRateEditDTO { - exchangeRate: number, -}; - -export interface IExchangeRateFilter { - page: number, - pageSize: number, - filterRoles?: IFilterRole[]; - columnSortBy: string; - sortOrder: string; -}; - -export interface IExchangeRatesService { - newExchangeRate(tenantId: number, exchangeRateDTO: IExchangeRateDTO): Promise; - editExchangeRate(tenantId: number, exchangeRateId: number, editExRateDTO: IExchangeRateEditDTO): Promise; - - deleteExchangeRate(tenantId: number, exchangeRateId: number): Promise; - listExchangeRates(tenantId: number, exchangeRateFilter: IExchangeRateFilter): Promise; -}; \ No newline at end of file +export interface EchangeRateLatestPOJO { + baseCurrency: string; + toCurrency: string; + exchangeRate: number; +} diff --git a/packages/server/src/lib/ExchangeRate/OpenExchangeRate.ts b/packages/server/src/lib/ExchangeRate/OpenExchangeRate.ts index 5f0a9b15b..221c5c5c5 100644 --- a/packages/server/src/lib/ExchangeRate/OpenExchangeRate.ts +++ b/packages/server/src/lib/ExchangeRate/OpenExchangeRate.ts @@ -18,6 +18,9 @@ export class OpenExchangeRate implements IExchangeRateService { baseCurrency: string, toCurrency: string ): Promise { + // Vaclidates the Open Exchange Rate api id early. + this.validateApiIdExistance(); + try { const result = await Axios.get(OPEN_EXCHANGE_RATE_LATEST_URL, { params: { @@ -32,9 +35,25 @@ export class OpenExchangeRate implements IExchangeRateService { } } + /** + * Validates the Open Exchange Rate api id. + * @throws {ServiceError} + */ + private validateApiIdExistance() { + const apiId = config.exchangeRate.openExchangeRate.appId; + + if (!apiId) { + throw new ServiceError( + EchangeRateErrors.EX_RATE_SERVICE_API_KEY_REQUIRED, + 'Invalid App ID provided. Please sign up at https://openexchangerates.org/signup, or contact support@openexchangerates.org.' + ); + } + } + /** * Handles the latest errors. * @param {any} error + * @throws {ServiceError} */ private handleLatestErrors(error: any) { if (error.response.data?.message === 'missing_app_id') { diff --git a/packages/server/src/services/ExchangeRates/ExchangeRateApplication.ts b/packages/server/src/services/ExchangeRates/ExchangeRateApplication.ts new file mode 100644 index 000000000..9e51c5d72 --- /dev/null +++ b/packages/server/src/services/ExchangeRates/ExchangeRateApplication.ts @@ -0,0 +1,21 @@ +import { Inject } from 'typedi'; +import { ExchangeRatesService } from './ExchangeRatesService'; +import { EchangeRateLatestPOJO, ExchangeRateLatestDTO } from '@/interfaces'; + +export class ExchangeRateApplication { + @Inject() + private exchangeRateService: ExchangeRatesService; + + /** + * Gets the latest exchange rate. + * @param {number} tenantId + * @param {ExchangeRateLatestDTO} exchangeRateLatestDTO + * @returns {Promise} + */ + public latest( + tenantId: number, + exchangeRateLatestDTO: ExchangeRateLatestDTO + ): Promise { + return this.exchangeRateService.latest(tenantId, exchangeRateLatestDTO); + } +} diff --git a/packages/server/src/services/ExchangeRates/ExchangeRatesService.ts b/packages/server/src/services/ExchangeRates/ExchangeRatesService.ts index bb2437abc..ae322cdff 100644 --- a/packages/server/src/services/ExchangeRates/ExchangeRatesService.ts +++ b/packages/server/src/services/ExchangeRates/ExchangeRatesService.ts @@ -1,16 +1,7 @@ -import { Service, Inject } from 'typedi'; -import { IExchangeRatesService } from '@/interfaces'; +import { Service } from 'typedi'; import { ExchangeRate } from '@/lib/ExchangeRate/ExchangeRate'; import { ExchangeRateServiceType } from '@/lib/ExchangeRate/types'; -interface ExchangeRateLatestDTO { - toCurrency: string; -} - -interface EchangeRateLatestPOJO { - baseCurrency: string; - toCurrency: string; - exchangeRate: number; -} +import { EchangeRateLatestPOJO, ExchangeRateLatestDTO } from '@/interfaces'; @Service() export class ExchangeRatesService {