var request = require('request');
var Table = require('cli-table');
var transactions = [];
var totalTransactionCount = null;
var pageNumber = 1;
var baseUrl = 'http://resttest.bench.co/transactions/';
var command = '-t'; //process.argv[2];
// Proper usage check + instructions
if (command === null) { //process.argv.length !== 3) {
console.log("Available commands:");
console.log("-b\tDisplay total balance");
console.log("-t\tDisplay all transactions");
console.log("-l\tDisplay transactions listed by category");
console.log("Usage: node resttest <command>");
return;
} else {
connect(baseUrl + pageNumber + '.json');
}
// connect to api and append transactions recursively
function connect(targetUrl){
request(targetUrl, function(error, head, body){
if (!error && head.statusCode == 200) {
var response = JSON.parse(body);
transactions = transactions.concat(response.transactions);
totalTransactionCount = response.totalCount;
if (transactions.length < totalTransactionCount) {
pageNumber = response.page + 1;
connect(baseUrl + pageNumber + '.json');
} else {
sortTransactions();
removeDuplicates();
executeOption();
}
}
});
}
// Choose output based on user option
function executeOption(){
switch(command) {
case "-b":
displayBalance(transactions);
break;
case "-t":
displayTransactions(transactions);
break;
case "-l":
displayCategories(transactions);
break;
}
}
// Sort transactions by date, if same date sort by amount
function sortTransactions(){
transactions = transactions.sort(function(a,b){
var dateA = Date.parse(a.Date);
var dateB = Date.parse(b.Date);
if (dateA === dateB) {
return a.Amount - b.Amount;
}
return dateA - dateB;
});
}
// Display total balance of all transactions
function displayBalance(){
balance = transactions.reduce(function(sum, transaction){
return sum += parseFloat(transaction.Amount);
}, 0);
console.log("Total Balance: " + balance);
}
// Takes in an array of transactions and displays them on a table
function displayTransactions(transactions){
var table = new Table({
head: ['Date', 'Ledger','Company','Amount','Balance'],
colWidths: [12, 40, 45, 12, 12],
colAligns: ['left','left','left','right', 'right']
});
var totals = 0;
transactions.forEach(function(transaction,i){
var formattedAmount = parseFloat(transaction.Amount).toFixed(2);
var formattedCompanyName = transaction.Company.replace(/[#x@]+/g,'').replace(/\d?[^.]\d{2,}/g,'').replace(/\s+/g,' ').trim();
totals += parseFloat(transaction.Amount);
if (transactions[i+1] && transaction.Date === transactions[i+1].Date) {
table.push([transaction.Date,transaction.Ledger,formattedCompanyName,formattedAmount, ""]);
} else {
table.push([transaction.Date,transaction.Ledger,formattedCompanyName,formattedAmount, parseFloat(totals).toFixed(2)]);
}
});
totals = parseFloat(totals).toFixed(2);
table.push(["", "", "Total", totals]);
console.log(table.toString());
}
// Separates transactions by categories (Ledger) and displays each category in a separate table
function displayCategories(transactions){
var categories = {};
transactions.forEach(function(transaction,i){
if (categories[transaction.Ledger]) {
categories[transaction.Ledger].push(transaction);
} else {
categories[transaction.Ledger] = [transaction];
}
});
for (var category in categories) {
displayTransactions(categories[category]);
}
}
// Compares two transactions, returns true for identical transactions, otherwise returns false
function compareTransactions(trans1,trans2){
if (
trans1 && trans2 &&
trans1.Company === trans2.Company &&
trans1.Date === trans2.Date &&
trans1.Ledger === trans2.Ledger &&
trans1.Amount === trans2.Amount
) {
return true;
} else {
return false;
}
}
// Checks transactions array for duplication and removes any duplicates
// Array needs to be sorted
function removeDuplicates(){
for (var i = 0; i<transactions.length; i++) {
if (compareTransactions(transactions[i-1],transactions[i])) {
transactions.splice(i, 1);
}
}
}