import { Service, Inject } from 'typedi'; import { Router, Request, Response, NextFunction } from 'express'; import { check, param, 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 DynamicListingService from '@/services/DynamicListing/DynamicListService'; @Service() export default class ExchangeRatesController extends BaseController { @Inject() exchangeRatesService: ExchangeRatesService; @Inject() dynamicListService: DynamicListingService; /** * Constructor method. */ router() { const router = Router(); router.get( '/', [...this.exchangeRatesListSchema], this.validationResult, asyncMiddleware(this.exchangeRates.bind(this)), this.dynamicListService.handlerErrorsToResponse, this.handleServiceError, ); router.post( '/', [...this.exchangeRateDTOSchema], this.validationResult, asyncMiddleware(this.addExchangeRate.bind(this)), this.handleServiceError ); router.post( '/:id', [...this.exchangeRateEditDTOSchema, ...this.exchangeRateIdSchema], this.validationResult, asyncMiddleware(this.editExchangeRate.bind(this)), this.handleServiceError ); router.delete( '/:id', [...this.exchangeRateIdSchema], this.validationResult, asyncMiddleware(this.deleteExchangeRate.bind(this)), this.handleServiceError ); return router; } get exchangeRatesListSchema() { return [ query('page').optional().isNumeric().toInt(), query('page_size').optional().isNumeric().toInt(), query('column_sort_by').optional(), query('sort_order').optional().isIn(['desc', 'asc']), ]; } get exchangeRateDTOSchema() { return [ check('exchange_rate').exists().isNumeric().toFloat(), check('currency_code').exists().trim().escape(), check('date').exists().isISO8601(), ]; } get exchangeRateEditDTOSchema() { return [check('exchange_rate').exists().isNumeric().toFloat()]; } get exchangeRateIdSchema() { return [param('id').isNumeric().toInt()]; } get exchangeRatesIdsSchema() { return [ query('ids').isArray({ min: 2 }), query('ids.*').isNumeric().toInt(), ]; } /** * Retrieve exchange rates. * @param {Request} req * @param {Response} res * @param {NextFunction} next */ async exchangeRates(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; const filter = { page: 1, pageSize: 12, filterRoles: [], columnSortBy: 'created_at', sortOrder: 'asc', ...this.matchedQueryData(req), }; if (filter.stringifiedFilterRoles) { filter.filterRoles = JSON.parse(filter.stringifiedFilterRoles); } try { const exchangeRates = await this.exchangeRatesService.listExchangeRates( tenantId, filter ); return res.status(200).send({ exchange_rates: exchangeRates }); } catch (error) { next(error); } } /** * Adds a new exchange rate on the given date. * @param {Request} req * @param {Response} res * @param {NextFunction} next */ async addExchangeRate(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; const exchangeRateDTO = this.matchedBodyData(req); try { const exchangeRate = await this.exchangeRatesService.newExchangeRate( tenantId, exchangeRateDTO ); return res.status(200).send({ id: exchangeRate.id }); } catch (error) { next(error); } } /** * Edit the given exchange rate. * @param {Request} req * @param {Response} res * @param {NextFunction} next */ async editExchangeRate(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; const { id: exchangeRateId } = req.params; const exchangeRateDTO = this.matchedBodyData(req); try { const exchangeRate = await this.exchangeRatesService.editExchangeRate( tenantId, exchangeRateId, exchangeRateDTO ); return res.status(200).send({ id: exchangeRateId, message: 'The exchange rate has been edited successfully.', }); } catch (error) { next(error); } } /** * Delete the given exchange rate from the storage. * @param {Request} req * @param {Response} res * @param {NextFunction} next */ async deleteExchangeRate(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; const { id: exchangeRateId } = req.params; try { await this.exchangeRatesService.deleteExchangeRate( tenantId, exchangeRateId ); return res.status(200).send({ id: exchangeRateId }); } catch (error) { next(error); } } /** * Handle service errors. * @param {Error} error * @param {Request} req * @param {Response} res * @param {NextFunction} next */ handleServiceError( error: Error, req: Request, res: Response, next: NextFunction ) { if (error instanceof ServiceError) { if (error.errorType === 'EXCHANGE_RATE_NOT_FOUND') { return res.status(404).send({ errors: [{ type: 'EXCHANGE.RATE.NOT.FOUND', code: 200 }], }); } if (error.errorType === 'NOT_FOUND_EXCHANGE_RATES') { return res.status(400).send({ errors: [{ type: 'EXCHANGE.RATES.IS.NOT.FOUND', code: 100 }], }); } if (error.errorType === 'EXCHANGE_RATE_PERIOD_EXISTS') { return res.status(400).send({ errors: [{ type: 'EXCHANGE.RATE.PERIOD.EXISTS', code: 300 }], }); } } next(error); } }