feat(server): add application layer to exchange rate service

This commit is contained in:
Ahmed Bouhuolia
2024-01-28 18:47:49 +02:00
parent ac7175d83b
commit 1b20d1b073
5 changed files with 54 additions and 50 deletions

View File

@@ -1,16 +1,16 @@
import { Service, Inject } from 'typedi'; import { Service, Inject } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express'; 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 asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseController from './BaseController'; import BaseController from './BaseController';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import { ExchangeRatesService } from '@/services/ExchangeRates/ExchangeRatesService';
import { EchangeRateErrors } from '@/lib/ExchangeRate/types'; import { EchangeRateErrors } from '@/lib/ExchangeRate/types';
import { ExchangeRateApplication } from '@/services/ExchangeRates/ExchangeRateApplication';
@Service() @Service()
export default class ExchangeRatesController extends BaseController { export default class ExchangeRatesController extends BaseController {
@Inject() @Inject()
private exchangeRatesService: ExchangeRatesService; private exchangeRatesApp: ExchangeRateApplication;
/** /**
* Constructor method. * Constructor method.
@@ -43,7 +43,7 @@ export default class ExchangeRatesController extends BaseController {
const exchangeRateQuery = this.matchedQueryData(req); const exchangeRateQuery = this.matchedQueryData(req);
try { try {
const exchangeRate = await this.exchangeRatesService.latest( const exchangeRate = await this.exchangeRatesApp.latest(
tenantId, tenantId,
exchangeRateQuery exchangeRateQuery
); );

View File

@@ -1,36 +1,9 @@
import { IFilterRole } from './DynamicFilter'; export interface ExchangeRateLatestDTO {
toCurrency: string;
}
export interface IExchangeRate { export interface EchangeRateLatestPOJO {
id: number, baseCurrency: string;
currencyCode: string, toCurrency: string;
exchangeRate: number, 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<IExchangeRate>;
editExchangeRate(tenantId: number, exchangeRateId: number, editExRateDTO: IExchangeRateEditDTO): Promise<void>;
deleteExchangeRate(tenantId: number, exchangeRateId: number): Promise<void>;
listExchangeRates(tenantId: number, exchangeRateFilter: IExchangeRateFilter): Promise<void>;
};

View File

@@ -18,6 +18,9 @@ export class OpenExchangeRate implements IExchangeRateService {
baseCurrency: string, baseCurrency: string,
toCurrency: string toCurrency: string
): Promise<number> { ): Promise<number> {
// Vaclidates the Open Exchange Rate api id early.
this.validateApiIdExistance();
try { try {
const result = await Axios.get(OPEN_EXCHANGE_RATE_LATEST_URL, { const result = await Axios.get(OPEN_EXCHANGE_RATE_LATEST_URL, {
params: { 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. * Handles the latest errors.
* @param {any} error * @param {any} error
* @throws {ServiceError}
*/ */
private handleLatestErrors(error: any) { private handleLatestErrors(error: any) {
if (error.response.data?.message === 'missing_app_id') { if (error.response.data?.message === 'missing_app_id') {

View File

@@ -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<EchangeRateLatestPOJO>}
*/
public latest(
tenantId: number,
exchangeRateLatestDTO: ExchangeRateLatestDTO
): Promise<EchangeRateLatestPOJO> {
return this.exchangeRateService.latest(tenantId, exchangeRateLatestDTO);
}
}

View File

@@ -1,16 +1,7 @@
import { Service, Inject } from 'typedi'; import { Service } from 'typedi';
import { IExchangeRatesService } from '@/interfaces';
import { ExchangeRate } from '@/lib/ExchangeRate/ExchangeRate'; import { ExchangeRate } from '@/lib/ExchangeRate/ExchangeRate';
import { ExchangeRateServiceType } from '@/lib/ExchangeRate/types'; import { ExchangeRateServiceType } from '@/lib/ExchangeRate/types';
interface ExchangeRateLatestDTO { import { EchangeRateLatestPOJO, ExchangeRateLatestDTO } from '@/interfaces';
toCurrency: string;
}
interface EchangeRateLatestPOJO {
baseCurrency: string;
toCurrency: string;
exchangeRate: number;
}
@Service() @Service()
export class ExchangeRatesService { export class ExchangeRatesService {