diff --git a/src/transaction/transaction.controller.spec.ts b/src/transaction/transaction.controller.spec.ts index 4c0c389..a8bf324 100644 --- a/src/transaction/transaction.controller.spec.ts +++ b/src/transaction/transaction.controller.spec.ts @@ -70,9 +70,9 @@ describe('TransactionController Unit Tests', () => { }); it('calling applyRules method minimum result of applied rules should be got', async () => { - const mockTransactionInput: TransactionInput = { + const mockTransactionInput = { date: '2021-01-05', - amount: '1000.00', + base_amount: 1000.0, currency: 'EUR', client_id: 1, }; diff --git a/src/transaction/transaction.controller.ts b/src/transaction/transaction.controller.ts index 0c50631..740794d 100644 --- a/src/transaction/transaction.controller.ts +++ b/src/transaction/transaction.controller.ts @@ -1,4 +1,5 @@ import { Controller, Post, UsePipes, Body } from '@nestjs/common'; +import { ExchangeRateInput, ExchangeRateResponse } from 'src/exchange-rate/exchange-rate.dto'; import { ExchangeRateService } from 'src/exchange-rate/exchange-rate.service'; import { TransactionService } from './transaction.service'; import { transactionBodySchema } from './transaction.validation'; @@ -11,6 +12,9 @@ import { DefaultCommissionAmount, HighTurnoverDiscount, } from './transaction.dto'; +import { Transaction } from './transaction.entity'; + +type TransactionRuleData = Pick; @Controller('transaction') export class TransactionController { @@ -37,7 +41,7 @@ export class TransactionController { }); } - getClientDeposit = async (transactionInput: TransactionInput) => { + getClientDeposit = async (transactionInput: TransactionRuleData) => { try { const deposit = await this.transactionService.findByClientIdWithinActualMonth( @@ -60,7 +64,7 @@ export class TransactionController { return 0; }; - turnoverRule = async (transactionInput: TransactionInput) => { + turnoverRule = async (transactionInput: TransactionRuleData) => { try { const clientDeposit = await this.getClientDeposit(transactionInput); if (clientDeposit) { @@ -71,24 +75,26 @@ export class TransactionController { } }; - discountRule(transactionInput: TransactionInput) { + discountRule(transactionInput: TransactionRuleData) { return transactionInput.client_id === 42 ? DiscountRuleForClientById.client_42 : false; } - defaultRule(transactionInput: TransactionInput) { + defaultRule(transactionInput: TransactionRuleData) { const commissionAmount = - (parseInt(transactionInput.amount) / 100) * - DefaultCommissionPercentage.percentage; + (transactionInput.base_amount * DefaultCommissionPercentage.percentage) / + 100; return commissionAmount < DefaultCommissionAmount.amount ? DefaultCommissionAmount.amount : commissionAmount; } async applyRules( - rules: ((transactionInput: TransactionInput) => any)[], - transactionInput: TransactionInput, + rules: (( + transactionInput: TransactionRuleData, + ) => number | false | undefined | Promise)[], + transactionInput: TransactionRuleData, ) { let commissionAmount; for (let i = 0; i < rules.length; i++) { @@ -105,60 +111,71 @@ export class TransactionController { : this.defaultRule(transactionInput); } - getAmountWithExchange(transactionInput: TransactionInput) { - const commissionAmount = this.applyRules( - [this.turnoverRule, this.discountRule], - transactionInput, - ); + getExchangeRate(exchangeRateInput: ExchangeRateInput) { + return new Promise((resolve, reject) => { + try { + this.exchangeRateService.convertCurrency(exchangeRateInput).subscribe({ + next: resolve, + error: reject, + }); + } catch (error) { + reject(error); + } + }); + } - const exhangeRateInput = { + async getAmountWithExchange(transactionInput: TransactionInput) { + const exchangeRateResponse = await this.getExchangeRate({ date: transactionInput.date, + }); + + const transactionAmount = parseInt(transactionInput.amount); + const transactionData = { + date: transactionInput.date, + amount: transactionAmount, + currency: transactionInput.currency, + client_id: transactionInput.client_id, + base_currency: Currency.EUR, + base_amount: + transactionAmount / exchangeRateResponse[transactionInput.currency], }; - try { - this.exchangeRateService.convertCurrency(exhangeRateInput).subscribe({ - next: (exchangeRateResponse) => - commissionAmount - .then((commission) => - this.transactionService.insertOne({ - date: transactionInput.date, - amount: parseInt(transactionInput.amount), - currency: transactionInput.currency, - client_id: transactionInput.client_id, - commission, - base_currency: Currency.EUR, - base_amount: - parseInt(transactionInput.amount) * - exchangeRateResponse[transactionInput.currency], - }), - ) - .catch((error) => console.log(error)), - error: (error) => { - console.log(error); - }, - }); - } catch (error) { - console.log(error); - } + const commissionAmount = this.applyRules( + [this.turnoverRule, this.discountRule], + transactionData, + ); + + commissionAmount + .then((commission) => + this.transactionService.insertOne({ + ...transactionData, + commission, + }), + ) + .catch((error) => console.log(error)); return commissionAmount; } async getAmountWithoutExchange(transactionInput: TransactionInput) { + const transactionData = { + date: transactionInput.date, + amount: parseInt(transactionInput.amount), + currency: transactionInput.currency, + client_id: transactionInput.client_id, + base_currency: Currency.EUR, + base_amount: parseInt(transactionInput.amount), + }; + const commissionAmount = await this.applyRules( [this.turnoverRule, this.discountRule], - transactionInput, + transactionData, ); try { this.transactionService .insertOne({ - date: transactionInput.date, - amount: parseInt(transactionInput.amount), - currency: transactionInput.currency, - client_id: transactionInput.client_id, + ...transactionData, commission: commissionAmount, - base_currency: Currency.EUR, - base_amount: parseInt(transactionInput.amount), }) .catch((error) => console.log(error)); } catch (error) {