This repository has been archived by the owner on Nov 8, 2022. It is now read-only.
forked from thisiskeith/margin-calc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
margincalc.js
134 lines (115 loc) · 3.46 KB
/
margincalc.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
'use strict';
var margincalc = {};
margincalc.validate = function (obj) {
// returns true if valid
var EX_PREFIX = 'margin-calc exception: ',
config = {
cost: [
'canCalculate',
'greaterThanZero'],
revenue: [
'canCalculate',
'greaterThanZero'],
grossMargin: [
'canCalculate',
'lessThan100']
},
tests = {
canCalculate: function (property, val) {
// property passed and must not be undefined, null, or NaN
if (typeof val === 'undefined' ||
val === null ||
val.length <= 0 ||
val != val) {
throw new Error(EX_PREFIX + property + ' must be a number.');
}
},
greaterThanZero: function (property, val) {
// cost or revenue must be > 0
if (parseFloat(val) <= 0) {
throw new Error(EX_PREFIX + property + ' entered must be greater than 0.');
}
},
lessThan100: function (property, val) {
// gross margin must be < 100%
if (parseFloat(val) >= 100) {
throw new Error(EX_PREFIX + property + ' entered must be less than 100%.');
}
}
},
i, j, l;
// throws immediately if obj input is not correct
if (!obj || typeof obj !== 'object') {
throw new Error(EX_PREFIX + ' Validation input must be an object.');
}
for (i in obj) {
j = 0;
if (obj.hasOwnProperty(i)) {
l = config[i].length;
for (; j < l; j += 1) {
if (tests[config[i][j]]) {
tests[config[i][j]](i, obj[i]);
} else {
throw new Error(EX_PREFIX + i + ' missing test from validation tests.');
}
}
}
}
return true;
};
margincalc.grossProfit = function (revenue, cost) {
try {
this.validate({
revenue: revenue,
cost: cost
});
} catch (e) {
throw new Error(e.message);
}
return revenue - cost;
};
margincalc.grossMarginPercentage = function (revenue, cost, precision) {
var p, g;
try {
this.validate({
revenue: revenue,
cost: cost
});
} catch (e) {
throw new Error(e.message);
}
precision = precision || 2;
p = this.grossProfit(revenue, cost);
g = parseFloat((p / revenue * 100).toFixed(precision));
return g;
};
margincalc.markUpPercentage = function (revenue, cost, precision) {
var p, m;
try {
this.validate({
revenue: revenue,
cost: cost
});
} catch (e) {
throw new Error(e.message);
}
precision = precision || 2;
p = this.grossProfit(revenue, cost);
m = parseFloat(((p / cost) * 100).toFixed(precision));
return m;
};
margincalc.revenueFromGrossMarginPercentage = function (gmPercentage, cost, precision) {
var revenue;
try {
this.validate({
grossMargin: gmPercentage,
cost: cost
});
} catch (e) {
throw new Error(e.message);
}
precision = precision || 2;
revenue = parseFloat(((100 * cost) / (100 - gmPercentage)).toFixed(precision));
return revenue;
};
module.exports = margincalc;