Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions banktransfer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const models = require('./models');
const {
exists, zrevrange, zadd, expire, zincrby,
} = require('./redis');

function processResult(amount) {
if (amount === 10) {
return {
success: false,
error: 'Bank transfer failed',
};
}
return {
success: true,
message: 'Transfer was successful',
};
}

const BANK_TRANSFER_PROCESSORS_SET_NAME = 'banktf_processors_list';

// function that calls paystack endpoint
function paystackBT(amount) {
return processResult(amount);
}

// function that calls flutterwave endpoint
function flutterwaveBT(amount) {
return processResult(amount);
}

// function that calls monnify endpoint
function monnifyBT(amount) {
return processResult(amount);
}

// general function that calls processor function based on processor
function processBankTransfer(processor, amount) {
if (processor === 'paystack') {
return paystackBT(amount);
}
if (processor === 'flutterwave') {
return flutterwaveBT(amount);
}
if (processor === 'monnify') {
return monnifyBT(amount);
}
}

// main function
async function transferToBank(amount) {
const processors = await models.bank_transfer_processors.find(
{ where: { enabled: true }, raw: true },
);
const setArray = [];
const setExists = await exists(BANK_TRANSFER_PROCESSORS_SET_NAME);

if (!setExists) {
processors.forEach((processor) => {
let score = 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OpesanyaAdebayo what is score?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're creating a scoring & ranking system, so each processor is given a score.

if (processor.position === 1) {
score = 30;
}
if (processor.position === 2) {
score = 10;
}
setArray.push(score);
setArray.push(processor.name);
});
await zadd(BANK_TRANSFER_PROCESSORS_SET_NAME, setArray);
await expire(BANK_TRANSFER_PROCESSORS_SET_NAME, 1800); // set should refresh in 30mins
}
const processorList = await zrevrange(BANK_TRANSFER_PROCESSORS_SET_NAME, 0, -1, 'WITHSCORES');

const [highestScoredProcessor] = processorList;

const bankTransferResult = processBankTransfer(highestScoredProcessor, amount);
if (!bankTransferResult.success) {
await zincrby(BANK_TRANSFER_PROCESSORS_SET_NAME, -10, highestScoredProcessor);
} else {
await zincrby(BANK_TRANSFER_PROCESSORS_SET_NAME, 10, highestScoredProcessor);
}
return bankTransferResult;
}

// await trasferToBank(10);
36 changes: 36 additions & 0 deletions migrations/20210220170629-create-bank-transfer-processors-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module.exports = {
up: async (queryInterface, Sequelize) => queryInterface.createTable('bank_transfer_processors', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
position: {
type: Sequelize.INTEGER,
allowNull: false,
},
enabled: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: true,
},
created_at: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('NOW'),
},
updated_at: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('NOW'),
},
}),

down: async (queryInterface, _Sequelize) => queryInterface.dropTable('bank_transfer_processors'),
};
48 changes: 48 additions & 0 deletions models/bank_transfer_processors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const { Model } = require('sequelize');

module.exports = (sequelize, DataTypes) => {
class BankTransferProcessors extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
}
BankTransferProcessors.init({
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
position: {
type: DataTypes.INTEGER,
allowNull: false,
},
enabled: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
},
created_at: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
},
updated_at: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'bank_transfer_processors',
underscored: true,
});
return BankTransferProcessors;
};
29 changes: 29 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"test": "echo \"Error: no test specified\" && exit 1",
"migrate": "sequelize db:migrate",
"migrate:undo": "sequelize db:migrate:undo",
"migrate:undo:all": "sequelize db:migrate:undo:all"
"migrate:undo:all": "sequelize db:migrate:undo:all",
"seed": "sequelize db:seed:all"
},
"keywords": [
"wallet",
Expand All @@ -22,6 +23,7 @@
"dotenv": "^8.2.0",
"joi": "^17.3.0",
"mysql2": "^2.2.5",
"redis": "^3.0.2",
"sequelize": "^6.3.5",
"sequelize-cli": "^6.2.0",
"uuid": "^8.3.2"
Expand Down
18 changes: 18 additions & 0 deletions redis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const redis = require('redis');
const { promisify } = require('util');

const client = redis.createClient();

client.on('error', (error) => {
console.error(error);
});

const zadd = promisify(client.zadd).bind(client);
const zrevrange = promisify(client.zrevrange).bind(client);
const exists = promisify(client.exists).bind(client);
const expire = promisify(client.expire).bind(client);
const zincrby = promisify(client.zincrby).bind(client);

module.exports = {
zadd, zrevrange, exists, expire, zincrby,
};
30 changes: 30 additions & 0 deletions seeders/20210220200445-populate-bank-transfer-processors-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = {
up: async (queryInterface, Sequelize) => queryInterface.bulkInsert('bank_transfer_processors', [
{
name: 'monnify',
position: 1,
enabled: true,
created_at: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
updated_at: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
},
{
name: 'paystack',
position: 2,
enabled: true,
created_at: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
updated_at: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
},
{
name: 'flutterwave',
position: 3,
enabled: true,
created_at: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
updated_at: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
},
],
{
updateOnDuplicate: ['name'],
}),

down: async (queryInterface, _Sequelize) => queryInterface.bulkDelete('bank_transfer_processors', null),
};