statements 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +22 -0
  4. data/bin/statements +8 -0
  5. data/lib/html/css/main.css +115 -0
  6. data/lib/html/css/main.css.map +7 -0
  7. data/lib/html/css/main.scss +173 -0
  8. data/lib/html/index.html +94 -0
  9. data/lib/html/js/main.coffee +146 -0
  10. data/lib/html/js/main.js +174 -0
  11. data/lib/html/js/main.js.map +10 -0
  12. data/lib/html/vendor/bootstrap/css/bootstrap-theme.css +469 -0
  13. data/lib/html/vendor/bootstrap/css/bootstrap.css +6331 -0
  14. data/lib/html/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
  15. data/lib/html/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg +229 -0
  16. data/lib/html/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
  17. data/lib/html/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
  18. data/lib/html/vendor/bootstrap/js/bootstrap.js +2320 -0
  19. data/lib/html/vendor/bootstrap-datepicker.js +1681 -0
  20. data/lib/html/vendor/datepicker3.css +786 -0
  21. data/lib/html/vendor/jquery-2.1.3.js +9205 -0
  22. data/lib/html/vendor/underscore.js +1416 -0
  23. data/lib/statements/cli.rb +17 -0
  24. data/lib/statements/database.rb +22 -0
  25. data/lib/statements/migrations/00_alpha.rb +43 -0
  26. data/lib/statements/models/account.rb +9 -0
  27. data/lib/statements/models/document.rb +29 -0
  28. data/lib/statements/models/transaction.rb +43 -0
  29. data/lib/statements/pdf_reader.rb +34 -0
  30. data/lib/statements/reader/common/st_george.rb +31 -0
  31. data/lib/statements/reader/st_george_credit_card.rb +53 -0
  32. data/lib/statements/reader/st_george_savings.rb +95 -0
  33. data/lib/statements/reader.rb +76 -0
  34. data/lib/statements/search.rb +48 -0
  35. data/lib/statements/server.rb +69 -0
  36. data/lib/statements/version.rb +3 -0
  37. data/lib/statements/views/footer.erb +6 -0
  38. data/lib/statements/views/row.erb +16 -0
  39. data/lib/statements/views/search.erb +25 -0
  40. data/lib/statements.rb +17 -0
  41. metadata +141 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ff2b7e3e918329fc0e03bec9e77b195c3843fda6
4
+ data.tar.gz: 42b4173c2c664d3e510d90946875b7ea0a028772
5
+ SHA512:
6
+ metadata.gz: 9e4050e7a812a5e0fa47ffd4441f9949e96f78b866b3aadf69547345bc0455c0b70671371e35e68a4b98f293be67874e2d8f956a8cbf8000cc341b01b157ed7b
7
+ data.tar.gz: 3f5c9a2c5abe973b48468fa660623c8d66de92f987c6168322cbd6ccaf41d163ee3df2a394bca7526ab7781a69b32d9f4fb91a7337ed203d0f3f24cb4543562a
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Neil E. Pearson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # Statements
2
+
3
+ Builds a database of bank account transaction history by reading PDF bank statements, and provides a simple web interface for browsing data.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ $ gem install statements
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ 1. `cd` to a directory containing all your bank statements.
14
+ 2. Run `statements` and wait for new statements to be parsed.
15
+ 3. Open `http://localhost:57473` in a browser.
16
+
17
+ ## Supported banks
18
+
19
+ - St. George Credit Cards
20
+ - St. George Cash Accounts
21
+
22
+ The list is small. Want it to grow? Send a pull request!
data/bin/statements ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $:.unshift lib unless $:.include? lib
5
+
6
+ require 'statements'
7
+
8
+ Statements::Cli.main Dir.pwd, ARGV
@@ -0,0 +1,115 @@
1
+ .container-fluid {
2
+ padding-top: 15px; }
3
+
4
+ #colour a:before {
5
+ content: "";
6
+ border: 1px solid transparent;
7
+ padding: 6px;
8
+ display: block;
9
+ border-radius: 15px; }
10
+ #colour a.colour-white:before {
11
+ background: white; }
12
+ #colour a.colour-red:before {
13
+ background: #a13f3e; }
14
+ #colour a.colour-yellow:before {
15
+ background: #e9d543; }
16
+ #colour a.colour-green:before {
17
+ background: #3f9d5a; }
18
+ #colour a.colour-cyan:before {
19
+ background: #99d7ff; }
20
+ #colour a.colour-blue:before {
21
+ background: #48609d; }
22
+ #colour a.colour-magenta:before {
23
+ background: #af6bd7; }
24
+
25
+ #content thead th {
26
+ padding-top: 0; }
27
+ #content td p {
28
+ margin: 0; }
29
+ #content td p.small {
30
+ color: #666; }
31
+ #content .amount,
32
+ #content tfoot tr > * {
33
+ text-align: right; }
34
+ #content .credit .amount:before {
35
+ content: "($"; }
36
+ #content .credit .amount:after {
37
+ content: ")"; }
38
+ #content .debit .amount:before,
39
+ #content tfoot td:before {
40
+ content: "$"; }
41
+ #content tr.colour-white {
42
+ background: white; }
43
+ #content tr.colour-red {
44
+ background: #ffefef; }
45
+ #content tr.colour-yellow {
46
+ background: #ffffd7; }
47
+ #content tr.colour-green {
48
+ background: #e9fce7; }
49
+ #content tr.colour-blue {
50
+ background: #ebeffd; }
51
+ #content tr.colour-cyan {
52
+ background: #e1f7f7; }
53
+ #content tr.colour-magenta {
54
+ background: #fbefff; }
55
+ #content tr > td,
56
+ #content tr > th {
57
+ background: inherit; }
58
+ #content tr.colour-white a.picker,
59
+ #content li.colour-white a {
60
+ background: white; }
61
+ #content tr.colour-red a.picker,
62
+ #content li.colour-red a {
63
+ background: #a13f3e; }
64
+ #content tr.colour-green a.picker,
65
+ #content li.colour-green a {
66
+ background: #3f9d5a; }
67
+ #content tr.colour-blue a.picker,
68
+ #content li.colour-blue a {
69
+ background: #48609d; }
70
+ #content tr.colour-cyan a.picker,
71
+ #content li.colour-cyan a {
72
+ background: #99d7ff; }
73
+ #content tr.colour-magenta a.picker,
74
+ #content li.colour-magenta a {
75
+ background: #af6bd7; }
76
+ #content tr.colour-yellow a.picker,
77
+ #content li.colour-yellow a {
78
+ background: #e9d543; }
79
+ #content td.colour {
80
+ width: 20px;
81
+ position: relative; }
82
+ #content td.colour a {
83
+ display: block;
84
+ border: 1px solid #eee;
85
+ border-radius: 10px;
86
+ width: 20px;
87
+ height: 20px; }
88
+ #content td.colour a:hover {
89
+ border-color: #ddd; }
90
+ #content td.colour ul {
91
+ list-style: none;
92
+ position: absolute;
93
+ display: block;
94
+ right: 100%;
95
+ top: 1px;
96
+ margin-bottom: 0;
97
+ width: 167px;
98
+ text-align: right;
99
+ background: white;
100
+ border: 1px solid #eee;
101
+ border-radius: 50px;
102
+ padding: 3px;
103
+ height: 28px; }
104
+ #content td.colour ul li {
105
+ display: inline-block;
106
+ margin-right: 3px; }
107
+ #content td.colour ul li:last-child {
108
+ margin-right: 0; }
109
+
110
+ footer {
111
+ font-size: .8em;
112
+ text-align: center;
113
+ padding: 20px 0; }
114
+
115
+ /*# sourceMappingURL=main.css.map */
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "mappings": "AASA,gBAAiB;EACf,WAAW,EAAE,IAAI;;AAKf,gBAAS;EACP,OAAO,EAAE,EAAE;EACX,MAAM,EAAE,qBAAqB;EAC7B,OAAO,EAAC,GAAG;EACX,OAAO,EAAE,KAAK;EACd,aAAa,EAAE,IAAI;AAErB,6BAAsB;EAAE,UAAU,EArB9B,KAAK;AAsBT,2BAAoB;EAAE,UAAU,EArB9B,OAAO;AAsBT,8BAAuB;EAAE,UAAU,EArB9B,OAAO;AAsBZ,6BAAsB;EAAE,UAAU,EArB9B,OAAO;AAsBX,4BAAqB;EAAE,UAAU,EApB9B,OAAO;AAqBV,4BAAqB;EAAE,UAAU,EAtB9B,OAAO;AAuBV,+BAAwB;EAAE,UAAU,EArB9B,OAAO;;AA2Bf,iBAAS;EACP,WAAW,EAAE,CAAC;AAGhB,aAAK;EACH,MAAM,EAAE,CAAC;EAET,mBAAQ;IACN,KAAK,EAAE,IAAI;AAIf;qBACa;EACX,UAAU,EAAE,KAAK;AAIjB,+BAAS;EAAE,OAAO,EAAE,IAAI;AACxB,8BAAQ;EAAE,OAAO,EAAE,GAAG;AAKtB;wBAAS;EAAE,OAAO,EAAE,GAAG;AAIvB,wBAAe;EACb,UAAU,EA9DkB,KAAK;AAgEnC,sBAAa;EACX,UAAU,EAhEgB,OAAO;AAkEnC,yBAAgB;EACd,UAAU,EAlEmB,OAAO;AAoEtC,wBAAe;EACb,UAAU,EApEkB,OAAO;AAsErC,uBAAc;EACZ,UAAU,EAtEiB,OAAO;AAwEpC,uBAAc;EACZ,UAAU,EAxEiB,OAAO;AA0EpC,0BAAiB;EACf,UAAU,EA1EoB,OAAO;AA4EvC;gBACK;EACH,UAAU,EAAE,OAAO;AAIvB;0BACkB;EAChB,UAAU,EA1FN,KAAK;AA6FX;wBACgB;EACd,UAAU,EA9FR,OAAO;AAiGX;0BACkB;EAChB,UAAU,EAjGN,OAAO;AAoGb;yBACiB;EACf,UAAU,EArGP,OAAO;AAwGZ;yBACiB;EACf,UAAU,EAzGP,OAAO;AA4GZ;4BACoB;EAClB,UAAU,EA7GJ,OAAO;AAgHf;2BACmB;EACjB,UAAU,EAtHL,OAAO;AAyHd,kBAAU;EACR,KAAK,EAAE,IAAI;EACX,QAAQ,EAAE,QAAQ;EAElB,oBAAE;IACA,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,cAAc;IACtB,aAAa,EAAE,IAAI;IACnB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IAEZ,0BAAQ;MACN,YAAY,EAAE,IAAI;EAItB,qBAAG;IACD,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAI;IACX,GAAG,EAAE,GAAG;IACR,aAAa,EAAE,CAAC;IAChB,KAAK,EAAE,KAAK;IACZ,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,MAAM,EAAE,cAAc;IACtB,aAAa,EAAE,IAAI;IACnB,OAAO,EAAE,GAAG;IACZ,MAAM,EAAE,IAAI;IAEZ,wBAAG;MACD,OAAO,EAAE,YAAY;MACrB,YAAY,EAAE,GAAG;MAEjB,mCAAa;QACX,YAAY,EAAE,CAAC;;AAQzB,MAAO;EACL,SAAS,EAAE,IAAI;EACf,UAAU,EAAE,MAAM;EAClB,OAAO,EAAE,MAAM",
4
+ "sources": ["main.scss"],
5
+ "names": [],
6
+ "file": "main.css"
7
+ }
@@ -0,0 +1,173 @@
1
+ // Colours
2
+ $white: white; $light-white: white;
3
+ $red: #a13f3e; $light-red: #ffefef;
4
+ $yellow: #e9d543; $light-yellow: #ffffd7;
5
+ $green: #3f9d5a; $light-green: #e9fce7;
6
+ $blue: #48609d; $light-blue: #ebeffd;
7
+ $cyan: #99d7ff; $light-cyan: #e1f7f7;
8
+ $magenta: #af6bd7; $light-magenta: #fbefff;
9
+
10
+ .container-fluid {
11
+ padding-top: 15px;
12
+ }
13
+
14
+ #colour {
15
+ a {
16
+ &:before {
17
+ content: "";
18
+ border: 1px solid transparent;
19
+ padding:6px;
20
+ display: block;
21
+ border-radius: 15px;
22
+ }
23
+ &.colour-white:before { background: $white; }
24
+ &.colour-red:before { background: $red; }
25
+ &.colour-yellow:before { background: $yellow; }
26
+ &.colour-green:before { background: $green; }
27
+ &.colour-cyan:before { background: $cyan; }
28
+ &.colour-blue:before { background: $blue; }
29
+ &.colour-magenta:before { background: $magenta; }
30
+ }
31
+ }
32
+
33
+ #content {
34
+
35
+ thead th {
36
+ padding-top: 0;
37
+ }
38
+
39
+ td p {
40
+ margin: 0;
41
+
42
+ &.small {
43
+ color: #666;
44
+ }
45
+ }
46
+
47
+ .amount,
48
+ tfoot tr > * {
49
+ text-align: right;
50
+ }
51
+
52
+ .credit .amount {
53
+ &:before { content: "($"; }
54
+ &:after { content: ")"; }
55
+ }
56
+
57
+ .debit .amount,
58
+ tfoot td {
59
+ &:before { content: "$"; }
60
+ }
61
+
62
+ tr {
63
+ &.colour-white {
64
+ background: $light-white;
65
+ }
66
+ &.colour-red {
67
+ background: $light-red;
68
+ }
69
+ &.colour-yellow {
70
+ background: $light-yellow;
71
+ }
72
+ &.colour-green {
73
+ background: $light-green;
74
+ }
75
+ &.colour-blue {
76
+ background: $light-blue;
77
+ }
78
+ &.colour-cyan {
79
+ background: $light-cyan;
80
+ }
81
+ &.colour-magenta {
82
+ background: $light-magenta;
83
+ }
84
+ > td,
85
+ > th {
86
+ background: inherit;
87
+ }
88
+ }
89
+
90
+ tr.colour-white a.picker,
91
+ li.colour-white a {
92
+ background: $white;
93
+ }
94
+
95
+ tr.colour-red a.picker,
96
+ li.colour-red a {
97
+ background: $red;
98
+ }
99
+
100
+ tr.colour-green a.picker,
101
+ li.colour-green a {
102
+ background: $green;
103
+ }
104
+
105
+ tr.colour-blue a.picker,
106
+ li.colour-blue a {
107
+ background: $blue;
108
+ }
109
+
110
+ tr.colour-cyan a.picker,
111
+ li.colour-cyan a {
112
+ background: $cyan;
113
+ }
114
+
115
+ tr.colour-magenta a.picker,
116
+ li.colour-magenta a {
117
+ background: $magenta;
118
+ }
119
+
120
+ tr.colour-yellow a.picker,
121
+ li.colour-yellow a {
122
+ background: $yellow;
123
+ }
124
+
125
+ td.colour {
126
+ width: 20px;
127
+ position: relative;
128
+
129
+ a {
130
+ display: block;
131
+ border: 1px solid #eee;
132
+ border-radius: 10px;
133
+ width: 20px;
134
+ height: 20px;
135
+
136
+ &:hover {
137
+ border-color: #ddd;
138
+ }
139
+ }
140
+
141
+ ul {
142
+ list-style: none;
143
+ position: absolute;
144
+ display: block;
145
+ right: 100%;
146
+ top: 1px;
147
+ margin-bottom: 0;
148
+ width: 167px;
149
+ text-align: right;
150
+ background: white;
151
+ border: 1px solid #eee;
152
+ border-radius: 50px;
153
+ padding: 3px;
154
+ height: 28px;
155
+
156
+ li {
157
+ display: inline-block;
158
+ margin-right: 3px;
159
+
160
+ &:last-child {
161
+ margin-right: 0;
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ }
168
+
169
+ footer {
170
+ font-size: .8em;
171
+ text-align: center;
172
+ padding: 20px 0;
173
+ }
@@ -0,0 +1,94 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Statements</title>
5
+ <meta charset="UTF-8">
6
+ <link rel="stylesheet" href="vendor/bootstrap/css/bootstrap.css"/>
7
+ <link rel="stylesheet" href="vendor/bootstrap/css/bootstrap-theme.css"/>
8
+ <link rel="stylesheet" href="vendor/datepicker3.css"/>
9
+ <link rel="stylesheet" href="css/main.css"/>
10
+ <script src="q/accounts.js"></script>
11
+ <script src="vendor/jquery-2.1.3.js"></script>
12
+ <script src="vendor/underscore.js"></script>
13
+ <script src="vendor/bootstrap/js/bootstrap.js"></script>
14
+ <script src="vendor/bootstrap-datepicker.js"></script>
15
+ <script src="js/main.js"></script>
16
+ </head>
17
+ <body>
18
+ <div class="container-fluid">
19
+ <div class="row">
20
+ <div class="col-sm-3 sidebar">
21
+ <form>
22
+ <div class="form-group">
23
+ <label for="order">Order</label>
24
+ <select id="order" name="order" class="form-control">
25
+ <option selected value="posted_at desc, document_line desc">Newest first</option>
26
+ <option value="posted_at asc, document_line desc">Oldest first</option>
27
+ <option value="description asc, posted_at asc, document_line asc">Alphabetical</option>
28
+ <option value="abs(amount) desc, description asc, posted_at asc, document_line asc">High value first</option>
29
+ <option value="abs(amount) asc, description asc, posted_at asc, document_line asc">Low value first</option>
30
+ </select>
31
+ </div>
32
+ <div class="form-group">
33
+ <label for="date-start">Period</label>
34
+ <div class="input-daterange input-group" id="date-range">
35
+ <input type="text" class="input-sm form-control" name="date-start" id="date-start" placeholder="Start"/>
36
+ <span class="input-group-addon">to</span>
37
+ <input type="text" class="input-sm form-control" name="date-end" id="date-end" placeholder="Finish"/>
38
+ </div>
39
+ </div>
40
+ <div class="form-group">
41
+ <label for="text">Search</label>
42
+ <input type="text"
43
+ class="form-control"
44
+ name="text"
45
+ id="text"
46
+ placeholder="Partial description"/>
47
+ </div>
48
+ <div class="form-group">
49
+ <label>Type</label>
50
+ <div id="type" class="btn-group btn-group-justified" role="group">
51
+ <a role="button" class="btn btn-default" data-type="credits">Credits</a>
52
+ <a role="button" class="btn btn-default active" data-type="both">Both</a>
53
+ <a role="button" class="btn btn-default" data-type="debits">Debits</a>
54
+ </div>
55
+ </div>
56
+ <div class="form-group">
57
+ <label>Colour</label>
58
+ <div id="colour" class="btn-group btn-group-justified" role="group" data-toggle="buttons">
59
+ <a role="button" class="btn btn-default active colour-white"></a>
60
+ <a role="button" class="btn btn-default active colour-red"></a>
61
+ <a role="button" class="btn btn-default active colour-yellow"></a>
62
+ <a role="button" class="btn btn-default active colour-green"></a>
63
+ <a role="button" class="btn btn-default active colour-cyan"></a>
64
+ <a role="button" class="btn btn-default active colour-blue"></a>
65
+ <a role="button" class="btn btn-default active colour-magenta"></a>
66
+ </div>
67
+ </div>
68
+ <div class="form-group">
69
+ <label>Accounts</label>
70
+ <div id="account-buttons"
71
+ class="btn-group-vertical btn-group-xs"
72
+ role="group"
73
+ style="width:100%"
74
+ data-toggle="buttons"></div>
75
+ <script>populate_accounts('#account-buttons')</script>
76
+ </div>
77
+ <div>
78
+ <div id="account-button-bulk" class="btn-group btn-group-justified" role="group">
79
+ <a role="button" class="btn btn-default" data-set="on">All</a>
80
+ <a role="button" class="btn btn-default" data-set="off">None</a>
81
+ </div>
82
+ </div>
83
+ </form>
84
+ <footer>
85
+ <p>For my Anna ❤️</p>
86
+ </footer>
87
+ </div>
88
+ <div id="content" class="col-sm-9 content">
89
+
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </body>
94
+ </html>
@@ -0,0 +1,146 @@
1
+ # List of colour literals
2
+ COLOURS = 'white red yellow green cyan blue magenta'.split ' '
3
+
4
+ # Populates the list of bank accounts in the sidebar
5
+ window.populate_accounts = (id) ->
6
+ $el = $(id)
7
+ for account in accounts
8
+ a = $('<a role="button" class="btn btn-default active" />')
9
+ a.text account.name
10
+ a.append '<br/>'
11
+ a.append $('<span class="small">').text(account.number)
12
+ a.data id: account.id
13
+ $el.append a
14
+
15
+ # AJAX layer
16
+ post = (page, data) -> $.ajax
17
+ url: "q/#{page}"
18
+ method: 'post'
19
+ contentType: 'application/json; charset=UTF-8'
20
+ dataType: page.match(/[^.]+$/)[0]
21
+ data: JSON.stringify data
22
+
23
+ # Method to query the database
24
+ querying = false
25
+ query_again = false
26
+ query = ->
27
+
28
+ # Handle interrupts
29
+ if querying
30
+ query_again = true
31
+ return
32
+ querying = true
33
+ query_again = false
34
+
35
+ # Clear content
36
+ $('#content').html 'One moment...'
37
+
38
+ # Submit data
39
+ req = post 'search.html',
40
+ order: $('#order').val()
41
+ date_start: $('#date-start').val()
42
+ date_end: $('#date-end').val()
43
+ search: $('#text').val()
44
+ type: $('#type .active').data 'type'
45
+ accounts: $('#account-buttons .active').map(-> $(@).data 'id').toArray()
46
+ colours: $('#colour .active').map(-> @className.match(/colour-(\w+)/)[1]).toArray()
47
+
48
+ # On success
49
+ req.done (result) -> $('#content').html result
50
+
51
+ # On fail
52
+ req.fail -> alert 'Query failed'
53
+
54
+ # Clean up
55
+ req.always ->
56
+ querying = false
57
+ query() if query_again
58
+
59
+ # Pad querying out a bit
60
+ query = _.debounce(query, 300)
61
+
62
+ # Method to change a transaction's colour
63
+ setColour = (transactionId, colour) -> post 'colour.json',
64
+ id: transactionId
65
+ colour: colour
66
+
67
+ $ ->
68
+ # Set the date range to last financial year
69
+ months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split ' '
70
+ range = end: new Date
71
+ range.end.setDate 1
72
+ range.end.setMonth range.end.getMonth() - 1 until range.end.getMonth() is 6
73
+ range.start = new Date(range.end)
74
+ range.start.setFullYear range.start.getFullYear() - 1
75
+ range.end.setDate range.end.getDate() - 1
76
+
77
+ $("#date-#{k}").val "#{i.getDate()} #{months[i.getMonth()]} #{i.getFullYear()}" for k, i of range
78
+
79
+ # Set up the date picker
80
+ $('.input-daterange').datepicker
81
+ format: "d M yyyy"
82
+ startView: 2
83
+ todayBtn: 'linked'
84
+ autoclose: true
85
+ .on 'changeDate', query
86
+
87
+ # Order
88
+ $('#order').on 'change', query
89
+
90
+ # Dates
91
+ $('date-range').on 'change', 'input', query
92
+
93
+ # Search
94
+ $('#text').on 'change keyup', query
95
+
96
+ # Colours
97
+ $('#colour').on 'click', 'a', query
98
+
99
+ # Account buttons
100
+ $accountButtons = $('#account-buttons a')
101
+ $accountButtons.on 'click', query
102
+
103
+ # Account select all/none buttons
104
+ $('#account-button-bulk').on 'click', 'a', (e) ->
105
+ set = $(e.currentTarget).data('set')
106
+ $accountButtons.toggleClass 'active', set is 'on'
107
+ query()
108
+
109
+ # Radio button behaviour for transaction types
110
+ $typeButtons = $('#type a')
111
+ $('#type').on 'click', 'a', (e) ->
112
+ return if $(e.currentTarget).hasClass 'active'
113
+ $typeButtons.each -> $(this).toggleClass 'active', this is e.currentTarget
114
+ query()
115
+
116
+ # Handler for blurring colour pickers
117
+ $picker = null
118
+ $('body').on 'click', (e) ->
119
+ target = e.currentTarget
120
+ closePicker() unless $picker and (target is $picker[0] or $picker.find(target)[0])
121
+
122
+ # Method to remove colour picker
123
+ closePicker = ->
124
+ $picker.remove() if $picker
125
+ $picker = null
126
+
127
+ # Handlers for clicks on colour pickers
128
+ $('#content').on 'click', 'td.colour a.picker', (e) ->
129
+ e.stopPropagation()
130
+ closePicker()
131
+ $tr = $(e.currentTarget).parents('tr').first()
132
+ $td = $tr.find('td.colour')
133
+ $picker = $('<ul class="colours">')
134
+ $picker.append $('<li>').addClass("colour-#{i}").append('<a href="javascript:">') for i in COLOURS
135
+ $picker.appendTo $td
136
+ $picker.on 'click', 'a', (e) ->
137
+ $li = $(e.currentTarget).parents('li').first()
138
+ colour = $li[0].className.match(/colour-(\w+)/)[1]
139
+ op = setColour $tr.data('id'), colour
140
+ op.fail -> alert 'Something went wrong. Try reloading?'
141
+ op.done -> $tr[0].className = $tr[0].className.replace /colour-\w+/, "colour-#{colour}"
142
+ closePicker()
143
+
144
+
145
+ # Do an initial query
146
+ query()