/
transaction.js
149 lines (118 loc) · 3.69 KB
/
transaction.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
146
147
148
149
var makeNumber = require('./lib/number/make-number')
var makeAbsoluteNumber = require('./lib/number/make-absolute-number')
var TransactionDate = require('./transaction-date')
/**
* Represents a single transaction.
* Getters and setters are used to transform and format values. Also responsible
* for calculating amounts and dates when missing or invalid.
* @constructor
* @param {Object} attributes
*/
function Transaction (attributes) {
this.attributes = {}
for (var key in attributes) {
if (attributes.hasOwnProperty(key)) this.set(key, attributes[key])
}
if (!this.get('date')) this.setDate()
if (!this.get('amount')) this.setAmount()
}
/**
* Functions that transform attributes as they are set
*/
Transaction.prototype.transformers = {
amount: makeNumber,
balance: makeNumber,
paidIn: makeAbsoluteNumber,
paidOut: makeAbsoluteNumber,
date: function (date) {
if (!(date instanceof Date)) return date
// Convert to GMT to ensure correct JSON values
date.setHours(date.getHours() - date.getTimezoneOffset() / 60)
return date
}
}
/**
* Functions that format attributes when retrieved with `getFormatted`
*/
Transaction.prototype.formatters = {
date: formatDate
}
/**
* Transforms and sets the given attribute
* @param {String} key - The name of the attribute
* @param value - The value of the attribute
*/
Transaction.prototype.set = function (key, value) {
var transformer = this.transformers[key] || idFunction
this.attributes[key] = transformer(value)
}
/**
* @returns the stored attribute
*/
Transaction.prototype.get = function (key) {
return this.attributes[key]
}
/**
* Get a value formatted by the corresponding formatter
* @param key - The key of the value to return
* @returns The formatted attribute
*/
Transaction.prototype.getFormatted = function (key) {
var formatter = this.formatters[key] || idFunction
return formatter(this.get(key))
}
/**
* Returns an array representation of the given keys or all formatted
* attributes.
* @param {Array} keys - An array of attribute keys
* @returns {Array} - An array of formatted attributes
*/
Transaction.prototype.toArray = function (keys) {
keys = keys || Object.keys(this.attributes)
return keys.map(this.getFormatted.bind(this))
}
/**
* Returns an object of formatted values of the given keys or all formatted
* attributes.
* @param {Array} keys - An array of attribute keys
* @returns {Array} - An array of formatted attributes
*/
Transaction.prototype.toJSON = function (keys) {
keys = keys || Object.keys(this.attributes)
var object = {}
for (var i = keys.length - 1; i >= 0; i--) {
var key = keys[i]
object[key] = this.getFormatted(key)
}
return object
}
Transaction.prototype.setDate = function (attrs) {
attrs = attrs || {}
var dateString = attrs.dateString || this.get('dateString')
var dateFormat = attrs.dateFormat || this.get('dateFormat')
var succeedingDate = attrs.succeedingDate
var transactionDate = new TransactionDate(dateString, dateFormat, {
succeedingDate: succeedingDate
})
this.set('transactionDate', transactionDate)
this.set('date', transactionDate.toDate())
}
Transaction.prototype.setAmount = function () {
var paidIn = this.get('paidIn')
var paidOut = this.get('paidOut')
this.set('amount', calculateAmount(paidIn, paidOut))
}
function calculateAmount (paidIn, paidOut) {
return paidIn || -paidOut
}
function formatDate (value) {
var yyyy = value.getFullYear()
var mm = padZeroes(value.getMonth() + 1)
var dd = padZeroes(value.getDate())
return [yyyy, mm, dd].join('-')
function padZeroes (number) {
return String('00' + number).slice(-2)
}
}
function idFunction (x) { return x }
module.exports = Transaction