refactor: extracted rule-applying code to a separate method (closes #10)

pull/21/head
Inga 🏳‍🌈 10 months ago
parent 8758bfb17e
commit fbd6fb52c1
  1. 11
      src/shared/rules.ts
  2. 84
      src/transaction/transaction.controller.spec.ts
  3. 25
      src/transaction/transaction.controller.ts

@ -0,0 +1,11 @@
import _ from 'lodash';
type RuleResult = number | false | undefined;
export const getMinimumRuleOutput = async <T>(
rules: ((input: T) => RuleResult | Promise<RuleResult>)[],
input: T,
) => {
const results = await Promise.all(rules.map((rule) => rule(input)));
return Math.min(..._.compact(results));
};

@ -71,91 +71,55 @@ describe('TransactionController Unit Tests', () => {
it('calling applyRules method minimum result of applied rules should be got', async () => { it('calling applyRules method minimum result of applied rules should be got', async () => {
{ {
const result = await transactionController.applyRules( const result = await transactionController.applyRules({
[ base_amount: 1000,
transactionController.discountRule, client_id: 1,
transactionController.turnoverRule, });
],
{
base_amount: 1000,
client_id: 1,
},
);
expect(result).to.eql(5); expect(result).to.eql(5);
} }
{ {
const result = await transactionController.applyRules( const result = await transactionController.applyRules({
[ base_amount: 1,
transactionController.discountRule, client_id: 1,
transactionController.turnoverRule, });
],
{
base_amount: 1,
client_id: 1,
},
);
expect(result).to.eql(0.05); expect(result).to.eql(0.05);
} }
{ {
const result = await transactionController.applyRules( const result = await transactionController.applyRules({
[ base_amount: 1000,
transactionController.discountRule, client_id: 42,
transactionController.turnoverRule, });
],
{
base_amount: 1000,
client_id: 42,
},
);
expect(result).to.eql(0.03); expect(result).to.eql(0.03);
} }
{ {
const result = await transactionController.applyRules( const result = await transactionController.applyRules({
[ base_amount: 1,
transactionController.discountRule, client_id: 42,
transactionController.turnoverRule, });
],
{
base_amount: 1,
client_id: 42,
},
);
expect(result).to.eql(0.03); expect(result).to.eql(0.03);
} }
{ {
const result = await transactionController.applyRules( const result = await transactionController.applyRules({
[ base_amount: 1000,
transactionController.discountRule, client_id: 99,
transactionController.turnoverRule, });
],
{
base_amount: 1000,
client_id: 99,
},
);
expect(result).to.eql(0.03); expect(result).to.eql(0.03);
} }
{ {
const result = await transactionController.applyRules( const result = await transactionController.applyRules({
[ base_amount: 1,
transactionController.discountRule, client_id: 99,
transactionController.turnoverRule, });
],
{
base_amount: 1,
client_id: 99,
},
);
expect(result).to.eql(0.03); expect(result).to.eql(0.03);
} }

@ -1,5 +1,4 @@
import { Controller, Post, UsePipes, Body } from '@nestjs/common'; import { Controller, Post, UsePipes, Body } from '@nestjs/common';
import _ from 'lodash';
import { import {
ExchangeRateInput, ExchangeRateInput,
ExchangeRateResponse, ExchangeRateResponse,
@ -17,6 +16,7 @@ import {
HighTurnoverDiscount, HighTurnoverDiscount,
} from './transaction.dto'; } from './transaction.dto';
import { Transaction } from './transaction.entity'; import { Transaction } from './transaction.entity';
import { getMinimumRuleOutput } from 'src/shared/rules';
type TransactionRuleData = Pick<Transaction, 'base_amount' | 'client_id'>; type TransactionRuleData = Pick<Transaction, 'base_amount' | 'client_id'>;
@ -90,16 +90,11 @@ export class TransactionController {
: commissionAmount; : commissionAmount;
} }
async applyRules( async applyRules(transactionInput: TransactionRuleData) {
rules: (( return getMinimumRuleOutput(
transactionInput: TransactionRuleData, [this.turnoverRule, this.discountRule, this.defaultRule],
) => number | false | undefined | Promise<number | false | undefined>)[], transactionInput,
transactionInput: TransactionRuleData,
) {
const commissions = await Promise.all(
[...rules, this.defaultRule].map((rule) => rule(transactionInput)),
); );
return Math.min(..._.compact(commissions));
} }
getExchangeRate(exchangeRateInput: ExchangeRateInput) { getExchangeRate(exchangeRateInput: ExchangeRateInput) {
@ -131,10 +126,7 @@ export class TransactionController {
transactionAmount / exchangeRateResponse[transactionInput.currency], transactionAmount / exchangeRateResponse[transactionInput.currency],
}; };
const commissionAmount = this.applyRules( const commissionAmount = this.applyRules(transactionData);
[this.turnoverRule, this.discountRule],
transactionData,
);
commissionAmount commissionAmount
.then((commission) => .then((commission) =>
@ -158,10 +150,7 @@ export class TransactionController {
base_amount: parseInt(transactionInput.amount), base_amount: parseInt(transactionInput.amount),
}; };
const commissionAmount = await this.applyRules( const commissionAmount = await this.applyRules(transactionData);
[this.turnoverRule, this.discountRule],
transactionData,
);
try { try {
this.transactionService this.transactionService
.insertOne({ .insertOne({

Loading…
Cancel
Save