Skip to content

Instantly share code, notes, and snippets.

@camisetags
Last active November 30, 2020 02:00
Show Gist options
  • Save camisetags/10b5656411c683646193acdbb606535e to your computer and use it in GitHub Desktop.
Save camisetags/10b5656411c683646193acdbb606535e to your computer and use it in GitHub Desktop.
transactionChallenge
// from codepad
var Mocha = require('mocha')
var mocha = new Mocha()
mocha.suite.emit('pre-require', this, 'solution', mocha)
var assert = require("chai").assert;
var transacts = [
{
id: 3,
sourceAccount: 'A',
targetAccount: 'B',
amount: 100,
category: 'eating_out',
time: '2018-03-02T10:34:30.000Z'
},
{
id: 1,
sourceAccount: 'A',
targetAccount: 'B',
amount: 100,
category: 'eating_out',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 6,
sourceAccount: 'A',
targetAccount: 'C',
amount: 250,
category: 'other',
time: '2018-03-02T10:33:05.000Z'
},
{
id: 4,
sourceAccount: 'A',
targetAccount: 'B',
amount: 100,
category: 'eating_out',
time: '2018-03-02T10:36:00.000Z'
},
{
id: 2,
sourceAccount: 'A',
targetAccount: 'B',
amount: 100,
category: 'eating_out',
time: '2018-03-02T10:33:50.000Z'
},
{
id: 5,
sourceAccount: 'A',
targetAccount: 'C',
amount: 250,
category: 'other',
time: '2018-03-02T10:33:00.000Z'
}
];
const transactsExpects = [
[
{
id: 1,
sourceAccount: "A",
targetAccount: "B",
amount: 100,
category: "eating_out",
time: "2018-03-02T10:33:00.000Z"
},
{
id: 2,
sourceAccount: "A",
targetAccount: "B",
amount: 100,
category: "eating_out",
time: "2018-03-02T10:33:50.000Z"
},
{
id: 3,
sourceAccount: "A",
targetAccount: "B",
amount: 100,
category: "eating_out",
time: "2018-03-02T10:34:30.000Z"
}
],
[
{
id: 5,
sourceAccount: "A",
targetAccount: "C",
amount: 250,
category: "other",
time: "2018-03-02T10:33:00.000Z"
},
{
id: 6,
sourceAccount: "A",
targetAccount: "C",
amount: 250,
category: "other",
time: "2018-03-02T10:33:05.000Z"
}
]
];
describe("findDuplicateTransactions()", function() {
it("returns empty array if there are no transactions", function() {
assert.deepEqual(findDuplicateTransactions([]), []);
});
it("returns correctness transactions", function() {
assert.deepEqual(findDuplicateTransactions(transacts), transactsExpects);
});
});
// Codepad again
mocha.run()
function groupBy( array , f ){
var groups = {};
array.forEach( function( o ){
var group = JSON.stringify( f(o) );
console.log(group);
groups[group] = groups[group] || [];
groups[group].push( o );
});
return Object.keys(groups).map( function( group ) {
return groups[group];
})
}
const findDuplicateTransactions = ( transactions = []) => {
var result = groupBy(transactions, function(item){
return [item.amount, item.sourceAccount, item.targetAccount, item.category];
});
return result.map((transactionList) => {
const convertedTransactions = transactionList
.map(transaction => ({
...transaction,
time: Date.parse(transaction.time)/1000
}))
.sort((prev, curr) => prev.time - curr.time)
.reduce((acc, cur, index) => {
const lastPos = acc[acc.length - 1] || cur;
return cur.time - lastPos.time < 60 || index === 0
? [...acc, cur]
: [...acc];
}, [])
.map((transaction) => ({
...transaction,
time: new Date(transaction.time * 1000).toISOString()
}));
return convertedTransactions;
});
}
console.log("############");
console.log(findDuplicateTransactions(transacts));
//Balance by category
//Calculate the balance in a specific category within the specified time period.
//getBalanceByCategoryInPeriod(transactionsList, category, startTime, endTime)
//Input
//You can assume that all parameters will always be present and valid.
//list of transactions (Transaction[])
//category (String)
//start time (inclusive) (Date)
//end time (exclusive) (Date)
//Output
//Total balance (Number)
//Negative number means money spent.
//Remember, this is what a transaction looks like:
//{
// id: 123,
// sourceAccount: 'my_account',
// targetAccount: 'coffee_shop',
// amount: -30,
// category: 'eating_out',
// time: '2018-03-12T12:34:00Z'
//}
// from codepad
var Mocha = require('mocha')
var mocha = new Mocha()
mocha.suite.emit('pre-require', this, 'solution', mocha)
var assert = require("chai").assert;
var transacts = [ {
id: 1,
sourceAccount: 'my_account',
targetAccount: 'coffee_shop',
amount: -30,
category: 'eating_out',
time: '2018-03-12T12:34:00Z'
},
{
id: 4,
sourceAccount: 'my_account',
targetAccount: 'coffee_shop',
amount: -60,
category: 'eating_out',
time: '2018-09-16'
},
{
id: 2,
sourceAccount: 'my_account',
targetAccount: 'coffee_shop',
amount: 300,
category: 'beauty',
time: '2018-09-15T12:34:00Z'
},
{
id: 3,
sourceAccount: 'my_account',
targetAccount: 'coffee_shop',
amount: 21,
category: 'beauty',
time: '2018-10-18T11:34:00Z'
},
];
function setEndDate(date) {
date = date ? new Date(date) : new Date();
if (date.getUTCHours() <= 0){
date.setDate(date.getDate() + 1);
date.setHours(0);
date.setMinutes(0);
}
return Date.parse(date);
}
function getBalanceByCategoryInPeriod(transactions = [], category, start, end) {
start = Date.parse(start);
end = setEndDate(end);
const trans = transactions
.map((transaction) => {
const { id, sourceAccount, targetAccount, ...cleanTransaction } = transaction;
return {
...cleanTransaction,
time: Date.parse(cleanTransaction.time)
};
}).filter((transaction) =>
!!end
? (transaction.category === category &&
(transaction.time >= start && transaction.time <= end))
: (transaction.category === category && transaction.time >= start)
).reduce((totalBalance, transaction) => totalBalance + transaction.amount, 0);
return trans;
}
describe("getBalanceByCategoryInPeriod()", () => {
it("returns 0 if there are no transactions", () => {
assert.equal(
getBalanceByCategoryInPeriod(
[],
"groceries",
new Date("2018-03-01"),
new Date("2018-03-31")
),
0
);
});
it("returns 321 with beauty category", () => {
assert.equal(
getBalanceByCategoryInPeriod(
transacts,
"beauty",
new Date("2018-09-15"),
new Date("2018-10-18")
),
321
);
});
it("returns 321 with beauty category without end date", () => {
assert.equal(
getBalanceByCategoryInPeriod(
transacts,
"beauty",
new Date("2018-09-15")
),
321
);
});
it("returns -90 with eating_out category", () => {
assert.equal(
getBalanceByCategoryInPeriod(
transacts,
"eating_out",
new Date("2018-02-11"),
new Date("2018-09-16")
),
-90
);
});
it("returns 0 with random values", () => {
assert.equal(
getBalanceByCategoryInPeriod(
[{ aaa: 'aaa', bbb: 'bbb' }],
"beauty",
new Date("2018-09-15")
),
0
);
});
it("includes transactions on start and excludes transactions on end", () => {
assert.equal(
getBalanceByCategoryInPeriod(
transacts,
"beauty",
new Date("2018-02-11"),
new Date("2020-09-16")
),
321
);
});
});
describe("setEndDate()", () => {
it("Return date complete datetime ", () => {
assert.equal(
setEndDate('2018-03-12T12:34:00Z'),
'1520858040000'
);
});
it("return date without time", () => {
assert.equal(
setEndDate("2018-05-10"),
1525996800000
);
});
it("Return a date without a param", () => {
assert.isNumber(
setEndDate("")
);
});
})
// Codepad again
mocha.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment