|
|
|
@ -1,5 +1,4 @@ |
|
|
|
|
import { Controller, Post, UsePipes, Body } from '@nestjs/common'; |
|
|
|
|
import _ from 'lodash'; |
|
|
|
|
import { |
|
|
|
|
ExchangeRateInput, |
|
|
|
|
ExchangeRateResponse, |
|
|
|
@ -17,6 +16,7 @@ import { |
|
|
|
|
HighTurnoverDiscount, |
|
|
|
|
} from './transaction.dto'; |
|
|
|
|
import { Transaction } from './transaction.entity'; |
|
|
|
|
import { getMinimumRuleOutput } from 'src/shared/rules'; |
|
|
|
|
|
|
|
|
|
type TransactionRuleData = Pick<Transaction, 'base_amount' | 'client_id'>; |
|
|
|
|
|
|
|
|
@ -33,10 +33,7 @@ export class TransactionController { |
|
|
|
|
@Body() transactionInput: TransactionInput, |
|
|
|
|
): Promise<string> { |
|
|
|
|
return JSON.stringify({ |
|
|
|
|
amount: |
|
|
|
|
transactionInput.currency !== Currency.EUR |
|
|
|
|
? (await this.getAmountWithExchange(transactionInput)).toFixed(2) |
|
|
|
|
: (await this.getAmountWithoutExchange(transactionInput)).toFixed(2), |
|
|
|
|
amount: (await this.getCommissionAmount(transactionInput)).toFixed(2), |
|
|
|
|
currency: Currency.EUR, |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -90,19 +87,14 @@ export class TransactionController { |
|
|
|
|
: commissionAmount; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async applyRules( |
|
|
|
|
rules: (( |
|
|
|
|
transactionInput: TransactionRuleData, |
|
|
|
|
) => number | false | undefined | Promise<number | false | undefined>)[], |
|
|
|
|
transactionInput: TransactionRuleData, |
|
|
|
|
) { |
|
|
|
|
const commissions = await Promise.all( |
|
|
|
|
[...rules, this.defaultRule].map((rule) => rule(transactionInput)), |
|
|
|
|
async applyRules(transactionInput: TransactionRuleData) { |
|
|
|
|
return getMinimumRuleOutput( |
|
|
|
|
[this.turnoverRule, this.discountRule, this.defaultRule], |
|
|
|
|
transactionInput, |
|
|
|
|
); |
|
|
|
|
return Math.min(..._.compact(commissions)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getExchangeRate(exchangeRateInput: ExchangeRateInput) { |
|
|
|
|
getExchangeRateResponse(exchangeRateInput: ExchangeRateInput) { |
|
|
|
|
return new Promise<ExchangeRateResponse>((resolve, reject) => { |
|
|
|
|
try { |
|
|
|
|
this.exchangeRateService.convertCurrency(exchangeRateInput).subscribe({ |
|
|
|
@ -115,11 +107,21 @@ export class TransactionController { |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async getAmountWithExchange(transactionInput: TransactionInput) { |
|
|
|
|
const exchangeRateResponse = await this.getExchangeRate({ |
|
|
|
|
async getExchangeRateIfNeeded(transactionInput: TransactionInput) { |
|
|
|
|
if (transactionInput.currency === Currency.EUR) { |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const exchangeRateResponse = await this.getExchangeRateResponse({ |
|
|
|
|
date: transactionInput.date, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return exchangeRateResponse[transactionInput.currency]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async getCommissionAmount(transactionInput: TransactionInput) { |
|
|
|
|
const exchangeRate = await this.getExchangeRateIfNeeded(transactionInput); |
|
|
|
|
|
|
|
|
|
const transactionAmount = parseInt(transactionInput.amount); |
|
|
|
|
const transactionData = { |
|
|
|
|
date: transactionInput.date, |
|
|
|
@ -127,53 +129,18 @@ export class TransactionController { |
|
|
|
|
currency: transactionInput.currency, |
|
|
|
|
client_id: transactionInput.client_id, |
|
|
|
|
base_currency: Currency.EUR, |
|
|
|
|
base_amount: |
|
|
|
|
transactionAmount / exchangeRateResponse[transactionInput.currency], |
|
|
|
|
base_amount: transactionAmount / exchangeRate, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const commissionAmount = this.applyRules( |
|
|
|
|
[this.turnoverRule, this.discountRule], |
|
|
|
|
transactionData, |
|
|
|
|
); |
|
|
|
|
const commission = await this.applyRules(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], |
|
|
|
|
transactionData, |
|
|
|
|
); |
|
|
|
|
try { |
|
|
|
|
this.transactionService |
|
|
|
|
.insertOne({ |
|
|
|
|
...transactionData, |
|
|
|
|
commission: commissionAmount, |
|
|
|
|
commission, |
|
|
|
|
}) |
|
|
|
|
.catch((error) => console.log(error)); |
|
|
|
|
} catch (error) { |
|
|
|
|
console.log(error); |
|
|
|
|
throw error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return commissionAmount; |
|
|
|
|
return commission; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|