feat(server): ability to assign the base currency as api query when getting latest ex. rate

This commit is contained in:
Ahmed Bouhuolia
2024-01-28 20:10:23 +02:00
parent 1740226294
commit 74a07847a4
6 changed files with 43 additions and 16 deletions

View File

@@ -1,6 +1,6 @@
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 { query } from 'express-validator'; import { query, oneOf } 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';
@@ -20,7 +20,12 @@ export default class ExchangeRatesController extends BaseController {
router.get( router.get(
'/latest', '/latest',
[query('to_currency').exists().isString()], [
oneOf([
query('to_currency').exists().isString().isISO4217(),
query('from_currency').exists().isString().isISO4217(),
]),
],
this.validationResult, this.validationResult,
asyncMiddleware(this.latestExchangeRate.bind(this)), asyncMiddleware(this.latestExchangeRate.bind(this)),
this.handleServiceError this.handleServiceError

View File

@@ -1,5 +1,6 @@
export interface ExchangeRateLatestDTO { export interface ExchangeRateLatestDTO {
toCurrency: string; toCurrency: string;
fromCurrency: string;
} }
export interface EchangeRateLatestPOJO { export interface EchangeRateLatestPOJO {

View File

@@ -2,6 +2,7 @@ import { Service } from 'typedi';
import { ExchangeRate } from '@/lib/ExchangeRate/ExchangeRate'; import { ExchangeRate } from '@/lib/ExchangeRate/ExchangeRate';
import { ExchangeRateServiceType } from '@/lib/ExchangeRate/types'; import { ExchangeRateServiceType } from '@/lib/ExchangeRate/types';
import { EchangeRateLatestPOJO, ExchangeRateLatestDTO } from '@/interfaces'; import { EchangeRateLatestPOJO, ExchangeRateLatestDTO } from '@/interfaces';
import { TenantMetadata } from '@/system/models';
@Service() @Service()
export class ExchangeRatesService { export class ExchangeRatesService {
@@ -15,14 +16,20 @@ export class ExchangeRatesService {
tenantId: number, tenantId: number,
exchangeRateLatestDTO: ExchangeRateLatestDTO exchangeRateLatestDTO: ExchangeRateLatestDTO
): Promise<EchangeRateLatestPOJO> { ): Promise<EchangeRateLatestPOJO> {
const organization = await TenantMetadata.query().findOne({ tenantId });
// Assign the organization base currency as a default currency
// if no currency is provided
const fromCurrency =
exchangeRateLatestDTO.fromCurrency || organization.baseCurrency;
const toCurrency =
exchangeRateLatestDTO.toCurrency || organization.baseCurrency;
const exchange = new ExchangeRate(ExchangeRateServiceType.OpenExchangeRate); const exchange = new ExchangeRate(ExchangeRateServiceType.OpenExchangeRate);
const exchangeRate = await exchange.latest( const exchangeRate = await exchange.latest(fromCurrency, toCurrency);
'USD',
exchangeRateLatestDTO.toCurrency
);
return { return {
baseCurrency: 'USD', baseCurrency: fromCurrency,
toCurrency: exchangeRateLatestDTO.toCurrency, toCurrency: exchangeRateLatestDTO.toCurrency,
exchangeRate, exchangeRate,
}; };

View File

@@ -1,6 +1,8 @@
import BaseModel from 'models/Model'; import BaseModel from 'models/Model';
export default class TenantMetadata extends BaseModel { export default class TenantMetadata extends BaseModel {
baseCurrency: string;
/** /**
* Table name. * Table name.
*/ */

View File

@@ -20,13 +20,16 @@ function AutoExchangeRateProvider({ children }: AutoExchangeRateProviderProps) {
// Retrieves the exchange rate. // Retrieves the exchange rate.
const { data: autoExchangeRate, isLoading: isAutoExchangeRateLoading } = const { data: autoExchangeRate, isLoading: isAutoExchangeRateLoading } =
useLatestExchangeRate(autoExRateCurrency, { useLatestExchangeRate(
enabled: Boolean(autoExRateCurrency), { fromCurrency: autoExRateCurrency },
refetchOnWindowFocus: false, {
staleTime: 0, enabled: Boolean(autoExRateCurrency),
cacheTime: 0, refetchOnWindowFocus: false,
retry: 0, staleTime: 0,
}); cacheTime: 0,
retry: 0,
},
);
const value = { const value = {
autoExRateCurrency, autoExRateCurrency,

View File

@@ -3,15 +3,23 @@ import { useQuery } from 'react-query';
import QUERY_TYPES from './types'; import QUERY_TYPES from './types';
import useApiRequest from '../useRequest'; import useApiRequest from '../useRequest';
interface LatestExchangeRateQuery {
fromCurrency?: string;
toCurrency?: string;
}
/** /**
* Retrieves latest exchange rate. * Retrieves latest exchange rate.
* @param {number} customerId - Customer id. * @param {number} customerId - Customer id.
*/ */
export function useLatestExchangeRate(toCurrency: string, props) { export function useLatestExchangeRate(
{ toCurrency, fromCurrency }: LatestExchangeRateQuery,
props,
) {
const apiRequest = useApiRequest(); const apiRequest = useApiRequest();
return useQuery( return useQuery(
[QUERY_TYPES.EXCHANGE_RATE, toCurrency], [QUERY_TYPES.EXCHANGE_RATE, toCurrency, fromCurrency],
() => () =>
apiRequest apiRequest
.http({ .http({
@@ -19,6 +27,7 @@ export function useLatestExchangeRate(toCurrency: string, props) {
method: 'get', method: 'get',
params: { params: {
to_currency: toCurrency, to_currency: toCurrency,
from_currency: fromCurrency,
}, },
}) })
.then((res) => res.data), .then((res) => res.data),