-
Notifications
You must be signed in to change notification settings - Fork 0
/
Money.js
145 lines (117 loc) · 3.9 KB
/
Money.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
135
136
137
138
139
140
141
142
143
144
145
var InvalidMoneyException = function (message) {
this.message = message;
this.name = "InvalidMoneyException";
};
function Money(amount, currency) {
this.validateAmount(amount);
this.amount = amount;
this.validateCurrency(currency);
this.currency = currency.toUpperCase();
}
Money.prototype = {
/**
* Access methods
*/
getAmount: function() {
return this.amount;
},
getCurrency: function() {
return this.currency;
},
/**
* Validation methods
*/
validateFloat: function(value) {
if(isNaN(parseFloat(value))) {
throw new InvalidMoneyException("The given value '" + value + "' is an invalid number");
}
},
validatePositiveAmount: function(amount) {
if(this.amount < 0) {
throw new InvalidMoneyException("The amount of money cannot be negative");
}
},
validateAmount: function(amount) {
this.validateFloat(amount);
this.validatePositiveAmount(amount);
},
validateCurrency: function(currency) {
var availableCurrencies = ["EUR", "USD", "BGN"]; // maybe comes from backend
currency = currency.toUpperCase();
// Validates currency in the list of available currencies
if(availableCurrencies.indexOf(currency) == -1) {
throw new InvalidMoneyException("The currency you have provided is invalid");
}
},
validateMoney: function(money) {
if(!money instanceof Money) {
throw new InvalidMoneyException("You can compare only objects of type Money");
}
if(this.getCurrency() != money.getCurrency()) {
throw new InvalidMoneyException("You can only compare money of the same currency");
}
},
validatePercentage: function(percentage) {
percentage = parseFloat(percentage);
if(isNaN(percentage)) {
throw new InvalidMoneyException("The percentage should be a float number in the range [0..100]");
}
if(percentage < 0 || percentage > 100) {
throw new InvalidMoneyException("The percentage should be a number in the range [0..100]");
}
},
/**
* Comparison
*/
equals: function(money) {
this.validateMoney(money);
return this.getAmount() == money.getAmount();
},
lessThan: function(money) {
this.validateMoney(money);
return this.getAmount() < money.getAmount();
},
lessThanOrEqualTo: function(money) {
this.validateMoney(money);
return this.getAmount() <= money.getAmount();
},
moreThan: function(money) {
this.validateMoney(money);
return this.getAmount() > money.getAmount();
},
moreThanOrEqualTo: function(money) {
this.validateMoney(money);
return this.getAmount() >= money.getAmount();
},
/**
* Operation
*/
add: function(money) {
this.validateMoney(money);
return new Money(this.getAmount() + money.getAmount(), this.currency);
},
subtract: function(money) {
this.validateMoney(money);
var amount = this.getAmount() - money.getAmount();
this.validatePositiveAmount(amount);
return new Money(amount, this.currency);
},
multiply: function(multiplier) {
this.validateFloat(multiplier);
return new Money(this.amount * multiplier, this.currency);
},
divide: function(divisor) {
this.validateFloat(divisor);
return new Money(this.amount * 100 / divisor / 100, this.currency);
},
allocate: function(percentage) {
this.validatePercentage(percentage);
percentage = parseFloat(percentage);
var allocated = Math.round(this.amount * percentage) / 100;
return [
new Money(allocated, this.currency),
new Money(this.amount - allocated, this.currency)
];
}
};
var exports = module.exports = Money;