forked from 9spokes/coding-challenge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
calc.js
109 lines (100 loc) · 3.37 KB
/
calc.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
const totalValueSumAccumulator = (accumulator, record) =>
record.total_value + accumulator;
/**
* filter out revenue records and add total_value to calculate revenue
* @param {Array} dataRecords array of data records
* @return {Number} calculated revenue
*/
function revenue(dataRecords) {
return dataRecords
.filter(record => record.account_category === 'revenue')
.reduce(totalValueSumAccumulator, 0);
}
/**
* filter out expense records and add total_value to calculate expenses
* @param {Array} dataRecords array of data records
* @return {Number} calculated expenses
*/
function expenses(dataRecords) {
return dataRecords
.filter(record => record.account_category === 'expense')
.reduce(totalValueSumAccumulator, 0);
}
/**
* add sales debits and divide by revenue
* @param {Array} dataRecords array of data records
* @param {Number} revenue calculated revenue
* @return {Number} calculated gross profit margin
*/
function grossProfitMargin(dataRecords, revenue) {
const salesDebits = dataRecords
.filter(
record => record.account_type === 'sales' && record.value_type === 'debit'
)
.reduce(totalValueSumAccumulator, 0);
return salesDebits / revenue;
}
/**
* calculates net profit margin from revenue and expenses
* @param {Number} revenue calculated revenue
* @param {Number} expenses calculated expenses
* @return {Number} calculated net profit margin
*/
function netProfitMargin(revenue, expenses) {
return (revenue - expenses) / revenue;
}
/**
* calculates net assets (debits minus credits)
* @param {Array} dataRecords array of data records
* @return {Number} net assets
*/
function netAssets(dataRecords) {
const isAsset = record =>
record.account_category === 'assets' &&
['current', 'bank', 'current_accounts_receivable'].includes(
record.account_type
);
const assetDebits = dataRecords
.filter(record => isAsset(record) && record.value_type === 'debit')
.reduce(totalValueSumAccumulator, 0);
const assetCredits = dataRecords
.filter(record => isAsset(record) && record.value_type === 'credit')
.reduce(totalValueSumAccumulator, 0);
return assetDebits - assetCredits;
}
/**
* calculates net liabilities (debits minus credits)
* @param {Array} dataRecords array of data records
* @return {Number} net liabilities
*/
function netLiabilities(dataRecords) {
const isLiability = record =>
record.account_category === 'liability' &&
['current', 'current_accounts_payable'].includes(record.account_type);
const liabilityDebits = dataRecords
.filter(record => isLiability(record) && record.value_type === 'debit')
.reduce(totalValueSumAccumulator, 0);
const liabilityCredits = dataRecords
.filter(record => isLiability(record) && record.value_type === 'credit')
.reduce(totalValueSumAccumulator, 0);
return liabilityDebits - liabilityCredits;
}
/**
* calculates working capital ratio
* @param {Array} dataRecords array of data records
* @return {number} calculated working capital ratio
*/
function workingCapitalRatio(dataRecords) {
const assets = netAssets(dataRecords);
const liabilities = netLiabilities(dataRecords);
return assets / liabilities;
}
module.exports = {
revenue,
expenses,
grossProfitMargin,
netProfitMargin,
workingCapitalRatio,
netAssets,
netLiabilities,
};