reckon 0.7.1 → 0.7.2
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +4 -4
- data/CHANGELOG.md +20 -5
- data/Gemfile.lock +1 -1
- data/Rakefile +2 -2
- data/bin/build-new-version.sh +1 -1
- data/bin/reckon +3 -0
- data/lib/reckon/app.rb +6 -6
- data/lib/reckon/cosine_similarity.rb +67 -62
- data/lib/reckon/money.rb +12 -5
- data/lib/reckon/options.rb +4 -0
- data/lib/reckon/version.rb +1 -1
- data/spec/cosine_training_and_test.rb +52 -0
- data/spec/integration/another_bank_example/output.ledger +3 -3
- data/spec/integration/ask_for_account/cli_input.exp +33 -0
- data/spec/integration/ask_for_account/expected_output +11 -0
- data/spec/integration/ask_for_account/input.csv +9 -0
- data/spec/integration/ask_for_account/test_args +1 -0
- data/spec/integration/broker_canada_example/output.ledger +2 -2
- data/spec/integration/chase/account_tokens_and_regex/output.ledger +3 -3
- data/spec/integration/chase/default_account_names/output.ledger +3 -3
- data/spec/integration/chase/learn_from_existing/output.ledger +3 -3
- data/spec/integration/chase/simple/output.ledger +3 -3
- data/spec/integration/danish_kroner_nordea_example/output.ledger +1 -1
- data/spec/integration/extratofake/output.ledger +1 -1
- data/spec/integration/harder_date_example/output.ledger +2 -2
- data/spec/integration/test.sh +52 -12
- data/spec/reckon/app_spec.rb +1 -1
- data/spec/reckon/csv_parser_spec.rb +3 -3
- data/spec/reckon/money_spec.rb +3 -3
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5984a4f8cd36d4e14f013c14bb111725f8681b90768b6710679820d1325a02e5
|
|
4
|
+
data.tar.gz: b392d89078a7679f01a344799512ec0467cfe8cad101374a5b8fd198c7e39480
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ae9b8348e93294d45354f1b96045305dd480b23cd34dcaca3f958fcbc866582000faa1711ea6cbb552578ffe98f126943221b98af298757b86e6dfa54c623f9d
|
|
7
|
+
data.tar.gz: f43e7128e198c9b73fc40b148cbe281d0bc02aeec90d576615e24fe98789a1846553121319152bffb3a9ca966fd26e1b3916da90480979c5d55106e06dbfe7f2
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -34,10 +34,10 @@ jobs:
|
|
|
34
34
|
- 2.3.7
|
|
35
35
|
steps:
|
|
36
36
|
- uses: actions/checkout@v2
|
|
37
|
+
- name: Update package
|
|
38
|
+
run: sudo apt-get update
|
|
37
39
|
- name: Install packages
|
|
38
|
-
run: sudo apt-get -y install ledger hledger
|
|
39
|
-
- name: Install bundler
|
|
40
|
-
run: sudo gem install -v 1.17.3 bundler
|
|
40
|
+
run: sudo apt-get -y install ledger hledger expect
|
|
41
41
|
- name: Set up Ruby
|
|
42
42
|
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
|
43
43
|
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
|
@@ -45,6 +45,6 @@ jobs:
|
|
|
45
45
|
# uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
|
46
46
|
with:
|
|
47
47
|
ruby-version: ${{ matrix.ruby-version }}
|
|
48
|
-
bundler-cache: true # runs 'bundle install' and caches installed gems
|
|
48
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems
|
|
49
49
|
- name: Run tests
|
|
50
50
|
run: bundle exec rake test_all
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [v0.7.
|
|
3
|
+
## [v0.7.2](https://github.com/cantino/reckon/tree/v0.7.2) (2021-04-22)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/cantino/reckon/compare/v0.7.1...v0.7.2)
|
|
6
|
+
|
|
7
|
+
**Closed issues:**
|
|
8
|
+
|
|
9
|
+
- \[feature request\] Better format for large transactions [\#108](https://github.com/cantino/reckon/issues/108)
|
|
10
|
+
- cosine similarity not comparing documents correctly [\#106](https://github.com/cantino/reckon/issues/106)
|
|
11
|
+
|
|
12
|
+
**Merged pull requests:**
|
|
13
|
+
|
|
14
|
+
- Add thousands separator in money output. Fixes \#108. [\#109](https://github.com/cantino/reckon/pull/109) ([benprew](https://github.com/benprew))
|
|
15
|
+
- Cosine similarity should use all docs tokens. not just matched tokens. [\#107](https://github.com/cantino/reckon/pull/107) ([benprew](https://github.com/benprew))
|
|
16
|
+
- Test getting expect working with actions [\#105](https://github.com/cantino/reckon/pull/105) ([benprew](https://github.com/benprew))
|
|
17
|
+
|
|
18
|
+
## [v0.7.1](https://github.com/cantino/reckon/tree/v0.7.1) (2021-02-07)
|
|
4
19
|
|
|
5
20
|
[Full Changelog](https://github.com/cantino/reckon/compare/v0.7.0...v0.7.1)
|
|
6
21
|
|
|
@@ -135,7 +150,6 @@
|
|
|
135
150
|
- Fix bugs in ledger file parsing. Fixes \#56. [\#81](https://github.com/cantino/reckon/pull/81) ([benprew](https://github.com/benprew))
|
|
136
151
|
- Better file encoding suggestions [\#80](https://github.com/cantino/reckon/pull/80) ([benprew](https://github.com/benprew))
|
|
137
152
|
- :bug: fix matching algorithm, add logging and a spec helper. Fixes \#73 [\#79](https://github.com/cantino/reckon/pull/79) ([benprew](https://github.com/benprew))
|
|
138
|
-
- bug: invalid header lines should be ignored, not parsed. [\#78](https://github.com/cantino/reckon/pull/78) ([benprew](https://github.com/benprew))
|
|
139
153
|
- convert default date format to iso8601 [\#77](https://github.com/cantino/reckon/pull/77) ([benprew](https://github.com/benprew))
|
|
140
154
|
- Fix rspec failure for ruby 2.3 and 2.4 [\#69](https://github.com/cantino/reckon/pull/69) ([BlackEdder](https://github.com/BlackEdder))
|
|
141
155
|
- Allow setting of money and date columns by index [\#67](https://github.com/cantino/reckon/pull/67) ([cantino](https://github.com/cantino))
|
|
@@ -188,6 +202,7 @@
|
|
|
188
202
|
|
|
189
203
|
**Merged pull requests:**
|
|
190
204
|
|
|
205
|
+
- bug: invalid header lines should be ignored, not parsed. [\#78](https://github.com/cantino/reckon/pull/78) ([benprew](https://github.com/benprew))
|
|
191
206
|
- Better ISO 8601 dates support [\#49](https://github.com/cantino/reckon/pull/49) ([vzctl](https://github.com/vzctl))
|
|
192
207
|
- Unattended mode and custom tokens support [\#47](https://github.com/cantino/reckon/pull/47) ([vzctl](https://github.com/vzctl))
|
|
193
208
|
- \[RFC\] Implement issue \#40: Tab completion [\#46](https://github.com/cantino/reckon/pull/46) ([BlackEdder](https://github.com/BlackEdder))
|
|
@@ -201,6 +216,7 @@
|
|
|
201
216
|
|
|
202
217
|
- Fix --encoding option [\#41](https://github.com/cantino/reckon/pull/41) ([mamciek](https://github.com/mamciek))
|
|
203
218
|
- Bumped version number [\#37](https://github.com/cantino/reckon/pull/37) ([BlackEdder](https://github.com/BlackEdder))
|
|
219
|
+
- Ing csv [\#30](https://github.com/cantino/reckon/pull/30) ([BlackEdder](https://github.com/BlackEdder))
|
|
204
220
|
|
|
205
221
|
## [v0.3.9](https://github.com/cantino/reckon/tree/v0.3.9) (2014-02-20)
|
|
206
222
|
|
|
@@ -217,15 +233,12 @@
|
|
|
217
233
|
- Date format [\#35](https://github.com/cantino/reckon/pull/35) ([BlackEdder](https://github.com/BlackEdder))
|
|
218
234
|
- Added example from a french bank [\#34](https://github.com/cantino/reckon/pull/34) ([BlackEdder](https://github.com/BlackEdder))
|
|
219
235
|
- Austrian example [\#33](https://github.com/cantino/reckon/pull/33) ([BlackEdder](https://github.com/BlackEdder))
|
|
220
|
-
- Ing csv [\#30](https://github.com/cantino/reckon/pull/30) ([BlackEdder](https://github.com/BlackEdder))
|
|
221
236
|
- Further improvements in nationwide csv handling [\#29](https://github.com/cantino/reckon/pull/29) ([BlackEdder](https://github.com/BlackEdder))
|
|
222
237
|
- Refactor: Add money class [\#28](https://github.com/cantino/reckon/pull/28) ([BlackEdder](https://github.com/BlackEdder))
|
|
223
238
|
- Initial split of CSVparser from class App [\#27](https://github.com/cantino/reckon/pull/27) ([BlackEdder](https://github.com/BlackEdder))
|
|
224
239
|
- Updated version of pull request 24: Allow for other currency symbols while calculating money\_score [\#26](https://github.com/cantino/reckon/pull/26) ([BlackEdder](https://github.com/BlackEdder))
|
|
225
240
|
- Change double column detection [\#23](https://github.com/cantino/reckon/pull/23) ([BlackEdder](https://github.com/BlackEdder))
|
|
226
|
-
- Added optional argument to contains\_header to skip multiple header lines [\#22](https://github.com/cantino/reckon/pull/22) ([BlackEdder](https://github.com/BlackEdder))
|
|
227
241
|
- Add a Bitdeli Badge to README [\#20](https://github.com/cantino/reckon/pull/20) ([bitdeli-chef](https://github.com/bitdeli-chef))
|
|
228
|
-
- Update README to show latest usage info [\#19](https://github.com/cantino/reckon/pull/19) ([purcell](https://github.com/purcell))
|
|
229
242
|
|
|
230
243
|
## [v0.3.8](https://github.com/cantino/reckon/tree/v0.3.8) (2013-07-03)
|
|
231
244
|
|
|
@@ -242,6 +255,7 @@
|
|
|
242
255
|
|
|
243
256
|
**Merged pull requests:**
|
|
244
257
|
|
|
258
|
+
- Update README to show latest usage info [\#19](https://github.com/cantino/reckon/pull/19) ([purcell](https://github.com/purcell))
|
|
245
259
|
- add support for spanish dates dd/mm/yyyy closes \#13 [\#14](https://github.com/cantino/reckon/pull/14) ([mauromorales](https://github.com/mauromorales))
|
|
246
260
|
- fix issue showing true when parsing the currency option related to \#7 [\#12](https://github.com/cantino/reckon/pull/12) ([mauromorales](https://github.com/mauromorales))
|
|
247
261
|
|
|
@@ -251,6 +265,7 @@
|
|
|
251
265
|
|
|
252
266
|
**Merged pull requests:**
|
|
253
267
|
|
|
268
|
+
- Added optional argument to contains\_header to skip multiple header lines [\#22](https://github.com/cantino/reckon/pull/22) ([BlackEdder](https://github.com/BlackEdder))
|
|
254
269
|
- Updated the sources to allow for custom curreny [\#11](https://github.com/cantino/reckon/pull/11) ([ghost](https://github.com/ghost))
|
|
255
270
|
- Add --account option on the commandline [\#10](https://github.com/cantino/reckon/pull/10) ([copiousfreetime](https://github.com/copiousfreetime))
|
|
256
271
|
|
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
|
@@ -17,6 +17,6 @@ task :test_all do
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
task :integration_tests do
|
|
20
|
-
|
|
21
|
-
raise 'Integration tests failed'
|
|
20
|
+
cmd = 'prove -v ./spec/integration/test.sh'
|
|
21
|
+
raise 'Integration tests failed' unless system(cmd)
|
|
22
22
|
end
|
data/bin/build-new-version.sh
CHANGED
|
@@ -5,7 +5,7 @@ set -e
|
|
|
5
5
|
VERSION=$1
|
|
6
6
|
|
|
7
7
|
echo "Install github_changelog_generator"
|
|
8
|
-
gem install --user github_changelog_generator
|
|
8
|
+
# gem install --user github_changelog_generator
|
|
9
9
|
|
|
10
10
|
echo "Update 'lib/reckon/version.rb'"
|
|
11
11
|
echo -e "module Reckon\n VERSION=\"$VERSION\"\nend" > lib/reckon/version.rb
|
data/bin/reckon
CHANGED
data/lib/reckon/app.rb
CHANGED
|
@@ -20,10 +20,10 @@ module Reckon
|
|
|
20
20
|
learn!
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def interactive_output(str)
|
|
23
|
+
def interactive_output(str, fh = $stdout)
|
|
24
24
|
return if options[:unattended]
|
|
25
25
|
|
|
26
|
-
puts str
|
|
26
|
+
fh.puts str
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def learn!
|
|
@@ -161,7 +161,7 @@ module Reckon
|
|
|
161
161
|
rows.sort_by { |n| [n[:date], -n[:money], n[:description]] }.each { |row| yield row }
|
|
162
162
|
end
|
|
163
163
|
|
|
164
|
-
def print_transaction(rows)
|
|
164
|
+
def print_transaction(rows, fh = $stdout)
|
|
165
165
|
str = "\n"
|
|
166
166
|
header = %w[Date Amount Description Note]
|
|
167
167
|
maxes = header.map(&:length)
|
|
@@ -185,7 +185,7 @@ module Reckon
|
|
|
185
185
|
str += "\n"
|
|
186
186
|
end
|
|
187
187
|
|
|
188
|
-
interactive_output str
|
|
188
|
+
interactive_output str, fh
|
|
189
189
|
end
|
|
190
190
|
|
|
191
191
|
def ask_account_question(msg, row)
|
|
@@ -280,12 +280,12 @@ module Reckon
|
|
|
280
280
|
exit
|
|
281
281
|
end
|
|
282
282
|
|
|
283
|
-
def output_table
|
|
283
|
+
def output_table(fh = $stdout)
|
|
284
284
|
rows = []
|
|
285
285
|
each_row_backwards do |row|
|
|
286
286
|
rows << row
|
|
287
287
|
end
|
|
288
|
-
print_transaction(rows)
|
|
288
|
+
print_transaction(rows, fh)
|
|
289
289
|
end
|
|
290
290
|
end
|
|
291
291
|
end
|
|
@@ -1,47 +1,52 @@
|
|
|
1
1
|
require 'matrix'
|
|
2
2
|
require 'set'
|
|
3
3
|
|
|
4
|
-
# Implementation of
|
|
5
|
-
#
|
|
4
|
+
# Implementation of cosine similarity using TF-IDF for vectorization.
|
|
5
|
+
#
|
|
6
|
+
# In information retrieval, tf–idf, short for term frequency–inverse document frequency,
|
|
7
|
+
# is a numerical statistic that is intended to reflect how important a word is to a
|
|
8
|
+
# document in a collection or corpus
|
|
9
|
+
#
|
|
10
|
+
# Cosine Similarity a measurement to determine how similar 2 documents are to each other.
|
|
11
|
+
#
|
|
12
|
+
# These weights and measures are used to suggest which account a transaction should be
|
|
13
|
+
# assigned to.
|
|
6
14
|
module Reckon
|
|
7
15
|
class CosineSimilarity
|
|
16
|
+
DocumentInfo = Struct.new(:tokens, :accounts)
|
|
17
|
+
|
|
8
18
|
def initialize(options)
|
|
19
|
+
@docs = DocumentInfo.new({}, {})
|
|
9
20
|
@options = options
|
|
10
|
-
@tokens = {}
|
|
11
|
-
@accounts = Hash.new(0)
|
|
12
21
|
end
|
|
13
22
|
|
|
14
23
|
def add_document(account, doc)
|
|
15
|
-
tokenize(doc)
|
|
24
|
+
tokens = tokenize(doc)
|
|
25
|
+
LOGGER.info "doc tokens: #{tokens}"
|
|
26
|
+
tokens.each do |n|
|
|
16
27
|
(token, count) = n
|
|
17
28
|
|
|
18
|
-
@tokens[token] ||=
|
|
19
|
-
@tokens[token][account]
|
|
20
|
-
@
|
|
21
|
-
@accounts[account] += count
|
|
29
|
+
@docs.tokens[token] ||= Hash.new(0)
|
|
30
|
+
@docs.tokens[token][account] += count
|
|
31
|
+
@docs.accounts[account] ||= Hash.new(0)
|
|
32
|
+
@docs.accounts[account][token] += count
|
|
22
33
|
end
|
|
23
34
|
end
|
|
24
35
|
|
|
25
36
|
# find most similar documents to query
|
|
26
37
|
def find_similar(query)
|
|
27
|
-
|
|
38
|
+
LOGGER.info "find_similar #{query}"
|
|
28
39
|
|
|
29
|
-
|
|
40
|
+
accounts = docs_to_check(query).map do |a|
|
|
41
|
+
[a, tfidf(@docs.accounts[a])]
|
|
42
|
+
end
|
|
30
43
|
|
|
31
|
-
|
|
32
|
-
suggestions = corpus_scores.map do |account, scores|
|
|
33
|
-
acct_vector = Vector.elements(scores, false)
|
|
44
|
+
q = tfidf(tokenize(query))
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
# similarity is a float between 1 and -1, where 1 is exactly the same and -1 is
|
|
37
|
-
# exactly opposite
|
|
38
|
-
# see https://en.wikipedia.org/wiki/Cosine_similarity
|
|
39
|
-
# cos(theta) = (A . B) / (||A|| ||B||)
|
|
40
|
-
# where A . B is the "dot product" and ||A|| is the magnitude of A
|
|
41
|
-
# ruby has the 'matrix' library we can use to do these calculations.
|
|
46
|
+
suggestions = accounts.map do |a, d|
|
|
42
47
|
{
|
|
43
|
-
similarity:
|
|
44
|
-
account:
|
|
48
|
+
similarity: calc_similarity(q, d),
|
|
49
|
+
account: a
|
|
45
50
|
}
|
|
46
51
|
end.select { |n| n[:similarity] > 0 }.sort_by { |n| -n[:similarity] }
|
|
47
52
|
|
|
@@ -52,50 +57,51 @@ module Reckon
|
|
|
52
57
|
|
|
53
58
|
private
|
|
54
59
|
|
|
55
|
-
def
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
corpus_scores = {}
|
|
59
|
-
query_scores = []
|
|
60
|
-
num_docs = @accounts.length
|
|
61
|
-
|
|
62
|
-
query_tokens.each do |n|
|
|
63
|
-
(token, _count) = n
|
|
64
|
-
next unless @tokens[token]
|
|
65
|
-
corpus = corpus.union(Set.new(@tokens[token].keys))
|
|
60
|
+
def docs_to_check(query)
|
|
61
|
+
return tokenize(query).reduce(Set.new) do |corpus, t|
|
|
62
|
+
corpus.union(Set.new(@docs.tokens[t[0]]&.keys))
|
|
66
63
|
end
|
|
64
|
+
end
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
# if no other docs have token, ignore it
|
|
72
|
-
next unless @tokens[token]
|
|
66
|
+
def tfidf(tokens)
|
|
67
|
+
scores = {}
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
@tokens[
|
|
79
|
-
|
|
69
|
+
tokens.each do |t, n|
|
|
70
|
+
scores[t] = calc_tf_idf(
|
|
71
|
+
n,
|
|
72
|
+
tokens.length,
|
|
73
|
+
@docs.tokens[t]&.length&.to_f || 0,
|
|
74
|
+
@docs.accounts.length
|
|
80
75
|
)
|
|
81
|
-
|
|
82
|
-
## Next, calculate for the corpus, where our "account" is a document
|
|
83
|
-
corpus.each do |account|
|
|
84
|
-
corpus_scores[account] ||= []
|
|
85
|
-
|
|
86
|
-
corpus_scores[account] << calc_tf_idf(
|
|
87
|
-
(@tokens[token][account] || 0),
|
|
88
|
-
@accounts[account].to_f,
|
|
89
|
-
@tokens[token].length.to_f,
|
|
90
|
-
num_docs
|
|
91
|
-
)
|
|
92
|
-
end
|
|
93
76
|
end
|
|
94
|
-
|
|
77
|
+
|
|
78
|
+
return scores
|
|
95
79
|
end
|
|
96
80
|
|
|
97
|
-
|
|
81
|
+
# Cosine similarity is used to compare how similar 2 documents are. Returns a float
|
|
82
|
+
# between 1 and -1, where 1 is exactly the same and -1 is exactly opposite.
|
|
83
|
+
#
|
|
84
|
+
# see https://en.wikipedia.org/wiki/Cosine_similarity
|
|
85
|
+
# cos(theta) = (A . B) / (||A|| ||B||)
|
|
86
|
+
# where A . B is the "dot product" and ||A|| is the magnitude of A
|
|
87
|
+
#
|
|
88
|
+
# The variables A and B are the set of unique terms in q and d.
|
|
89
|
+
#
|
|
90
|
+
# For example, when q = "big red balloon" and d ="small green balloon" then the
|
|
91
|
+
# variables are (big,red,balloon,small,green) and a = (1,1,1,0,0) and b =
|
|
92
|
+
# (0,0,1,1,1).
|
|
93
|
+
#
|
|
94
|
+
# query and doc are hashes of token => tf/idf score
|
|
95
|
+
def calc_similarity(query, doc)
|
|
96
|
+
tokens = Set.new(query.keys + doc.keys)
|
|
97
|
+
|
|
98
|
+
a = Vector.elements(tokens.map { |n| query[n] || 0 }, false)
|
|
99
|
+
b = Vector.elements(tokens.map { |n| doc[n] || 0 }, false)
|
|
100
|
+
|
|
101
|
+
return a.inner_product(b) / (a.magnitude * b.magnitude)
|
|
102
|
+
end
|
|
98
103
|
|
|
104
|
+
def calc_tf_idf(token_count, num_words_in_doc, df, num_docs)
|
|
99
105
|
# tf(t,d) = count of t in d / number of words in d
|
|
100
106
|
tf = token_count / num_words_in_doc.to_f
|
|
101
107
|
|
|
@@ -109,14 +115,13 @@ module Reckon
|
|
|
109
115
|
end
|
|
110
116
|
|
|
111
117
|
def tokenize(str)
|
|
112
|
-
mk_tokens(str).
|
|
118
|
+
mk_tokens(str).each_with_object(Hash.new(0)) do |n, memo|
|
|
113
119
|
memo[n] += 1
|
|
114
|
-
memo
|
|
115
120
|
end.to_a
|
|
116
121
|
end
|
|
117
122
|
|
|
118
123
|
def mk_tokens(str)
|
|
119
|
-
str.downcase.tr(';', ' ').tr("'", '').split(/[^a-z0-9.]+/)
|
|
124
|
+
str.downcase.tr(';', ' ').tr("'", '').split(/[^a-z0-9.]+/).reject(&:empty?)
|
|
120
125
|
end
|
|
121
126
|
end
|
|
122
127
|
end
|
data/lib/reckon/money.rb
CHANGED
|
@@ -50,11 +50,18 @@ module Reckon
|
|
|
50
50
|
return @amount_raw[0] == '-' ? @amount_raw[1..-1] : "-#{@amount_raw}"
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
amt = pretty_amount(@amount * (negate ? -1 : 1))
|
|
54
|
+
amt = if @suffixed
|
|
55
|
+
"#{amt} #{@currency}"
|
|
56
|
+
else
|
|
57
|
+
amt.gsub(/^((-)|)(?=\d)/, "\\1#{@currency}")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
return (@amount >= 0 ? " " : "") + amt
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def pretty_amount(amount)
|
|
64
|
+
sprintf("%0.2f", amount).reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
|
58
65
|
end
|
|
59
66
|
|
|
60
67
|
def parse(value, options = {})
|
data/lib/reckon/options.rb
CHANGED
|
@@ -85,6 +85,10 @@ module Reckon
|
|
|
85
85
|
options[:account_tokens_file] = a
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
opts.on("", "--table-output-file FILE") do |n|
|
|
89
|
+
options[:table_output_file] = n
|
|
90
|
+
end
|
|
91
|
+
|
|
88
92
|
options[:default_into_account] = 'Expenses:Unknown'
|
|
89
93
|
opts.on("", "--default-into-account NAME", "Default into account") do |a|
|
|
90
94
|
options[:default_into_account] = a
|
data/lib/reckon/version.rb
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'pp'
|
|
4
|
+
|
|
5
|
+
require 'reckon'
|
|
6
|
+
|
|
7
|
+
ledger_file = ARGV[0]
|
|
8
|
+
account = ARGV[1]
|
|
9
|
+
seed = ARGV[2] ? ARGV[2].to_i : Random.new_seed
|
|
10
|
+
|
|
11
|
+
ledger = Reckon::LedgerParser.new(File.read(ledger_file))
|
|
12
|
+
matcher = Reckon::CosineSimilarity.new({})
|
|
13
|
+
|
|
14
|
+
train = []
|
|
15
|
+
test = []
|
|
16
|
+
|
|
17
|
+
def has_account(account, entry)
|
|
18
|
+
entry[:accounts].map { |a| a[:name] }.include?(account)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
entries = ledger.entries.select { |e| has_account(account, e) }
|
|
22
|
+
|
|
23
|
+
r = Random.new(seed)
|
|
24
|
+
entries.length.times do |i|
|
|
25
|
+
r.rand < 0.9 ? train << i : test << i
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
train.each do |i|
|
|
29
|
+
entry = entries[i]
|
|
30
|
+
entry[:accounts].each do |a|
|
|
31
|
+
matcher.add_document(
|
|
32
|
+
a[:name],
|
|
33
|
+
[entry[:desc], a[:amount]].join(" ")
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
result = [nil] * test.length
|
|
39
|
+
test.each do |i|
|
|
40
|
+
entry = entries[i]
|
|
41
|
+
matches = matcher.find_similar(
|
|
42
|
+
entry[:desc] + " " + entry[:accounts][0][:amount].to_s
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if !matches[0] || !has_account(matches[0][:account], entry)
|
|
46
|
+
result[i] = [entry, matches]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# pp result.compact
|
|
51
|
+
puts "using #{seed} as random seed"
|
|
52
|
+
puts "true: #{result.count(nil)} false: #{result.count { |v| !v.nil? }}"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
2003-12-24 CREDIT; Some Company vendorpymt PPD ID: 5KL3832735
|
|
2
|
-
Assets:Bank:Checking $
|
|
2
|
+
Assets:Bank:Checking $2,105.00
|
|
3
3
|
Income:Unknown
|
|
4
4
|
|
|
5
5
|
2004-12-24 CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
Expenses:Unknown
|
|
16
16
|
|
|
17
17
|
2007-12-24 CREDIT; Blarg BLARG REVENUE PPD ID: 00jah78563
|
|
18
|
-
Assets:Bank:Checking $
|
|
18
|
+
Assets:Bank:Checking $1,558.52
|
|
19
19
|
Income:Unknown
|
|
20
20
|
|
|
21
21
|
2008-12-24 CREDIT; Some Company vendorpymt PPD ID: 59728JSL20
|
|
22
|
-
Assets:Bank:Checking $
|
|
22
|
+
Assets:Bank:Checking $3,520.00
|
|
23
23
|
Income:Unknown
|
|
24
24
|
|
|
25
25
|
2009-12-24 DEBIT; GITHUB 041287430274 CA 12/22GITHUB 04
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/expect -f
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
set timeout 7
|
|
5
|
+
match_max 100000
|
|
6
|
+
expect "What is this account named in Ledger |Assets:Bank:Checking|?\r
|
|
7
|
+
\[1G▽\[6n"
|
|
8
|
+
send -- "\[45;2R"
|
|
9
|
+
expect -exact "\[1G\[K\[6n"
|
|
10
|
+
send -- "\[45;1R"
|
|
11
|
+
expect "\[1G\[K\[1G\[1G"
|
|
12
|
+
send -- "T"
|
|
13
|
+
expect "\[1GT\[K\[1G\[2G"
|
|
14
|
+
send -- "e"
|
|
15
|
+
expect "\[1GTe\[K\[1G\[3G"
|
|
16
|
+
send -- "s"
|
|
17
|
+
expect "\[1GTes\[K\[1G\[4G"
|
|
18
|
+
send -- "t"
|
|
19
|
+
expect "\[1GTest\[K\[1G\[5G"
|
|
20
|
+
send -- ":"
|
|
21
|
+
expect "\[1GTest:\[K\[1G\[6G"
|
|
22
|
+
send -- ":"
|
|
23
|
+
expect "\[1GTest::\[K\[1G\[7G"
|
|
24
|
+
send -- "B"
|
|
25
|
+
expect "\[1GTest::B\[K\[1G\[8G"
|
|
26
|
+
send -- "a"
|
|
27
|
+
expect "\[1GTest::Ba\[K\[1G\[9G"
|
|
28
|
+
send -- "n"
|
|
29
|
+
expect "\[1GTest::Ban\[K\[1G\[10G"
|
|
30
|
+
send -- "k"
|
|
31
|
+
expect "\[1GTest::Bank\[K\[1G\[11G"
|
|
32
|
+
send -- "\r"
|
|
33
|
+
expect eof
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
Date | Amount | Description | Note |
|
|
3
|
+
2003-12-24 | $2,105.00 | CREDIT; Some Company vendorpymt PPD ID: 5KL3832735 | |
|
|
4
|
+
2004-12-24 | -$116.22 | CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL | |
|
|
5
|
+
2005-12-24 | -$0.96 | DEBIT; WEBSITE-BALANCE-10DEC09 12 12/10WEBSITE-BAL | |
|
|
6
|
+
2006-12-24 | $0.23 | DEBIT; WEBSITE-BALANCE-17DEC09 12 12/17WEBSITE-BAL | |
|
|
7
|
+
2007-12-24 | $1,558.52 | CREDIT; Blarg BLARG REVENUE PPD ID: 00jah78563 | |
|
|
8
|
+
2008-12-24 | $3,520.00 | CREDIT; Some Company vendorpymt PPD ID: 59728JSL20 | |
|
|
9
|
+
2009-12-24 | -$7.00 | DEBIT; GITHUB 041287430274 CA 12/22GITHUB 04 | |
|
|
10
|
+
2010-12-24 | -$20.00 | CHECK; CHECK 2656 | |
|
|
11
|
+
2011-12-24 | -$85.00 | DEBIT; HOST 037196321563 MO 12/22SLICEHOST | |
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
DEBIT,2011/12/24,"HOST 037196321563 MO 12/22SLICEHOST",($85.00)
|
|
2
|
+
CHECK,2010/12/24,"CHECK 2656",($20.00)
|
|
3
|
+
DEBIT,2009/12/24,"GITHUB 041287430274 CA 12/22GITHUB 04",($7.00)
|
|
4
|
+
CREDIT,2008/12/24,"Some Company vendorpymt PPD ID: 59728JSL20",$3520.00
|
|
5
|
+
CREDIT,2007/12/24,"Blarg BLARG REVENUE PPD ID: 00jah78563",$1558.52
|
|
6
|
+
DEBIT,2006/12/24,"WEBSITE-BALANCE-17DEC09 12 12/17WEBSITE-BAL",$.23
|
|
7
|
+
DEBIT,2005/12/24,"WEBSITE-BALANCE-10DEC09 12 12/10WEBSITE-BAL",($0.96)
|
|
8
|
+
CREDIT,2004/12/24,"PAYPAL TRANSFER PPD ID: PAYPALSDSL",($116.22)
|
|
9
|
+
CREDIT,2003/12/24,"Some Company vendorpymt PPD ID: 5KL3832735",$2105.00
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
-f input.csv -p
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
2013-06-19 2013-06-24; Buy; ISHARES S&P/TSX CAPPED REIT IN; XRE; 300; 15.90; CDN; CAD
|
|
10
10
|
Income:Unknown
|
|
11
|
-
Assets:Bank:Checking -$
|
|
11
|
+
Assets:Bank:Checking -$4,779.95
|
|
12
12
|
|
|
13
13
|
2013-06-27 2013-06-27; Dividend; ICICI BK SPONSORED ADR; IBN; 100; USD
|
|
14
14
|
Assets:Bank:Checking $66.70
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
Income:Unknown
|
|
20
20
|
|
|
21
21
|
2014-01-07 2014-01-10; Sell; BMO NASDAQ 100 EQTY HEDGED TO; ZQQ; -300; 27.44; CDN; CAD
|
|
22
|
-
Assets:Bank:Checking $
|
|
22
|
+
Assets:Bank:Checking $8,222.05
|
|
23
23
|
Income:Unknown
|
|
24
24
|
|
|
25
25
|
2014-01-07 2014-01-07; Interest; BMO S&P/TSX EQUAL WEIGHT BKS I; ZEB; 250; CAD
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
2009-12-10 CREDIT; Some Company vendorpymt PPD ID: 5KL3832735
|
|
2
|
-
Assets:Bank:Checking $
|
|
2
|
+
Assets:Bank:Checking $2,105.00
|
|
3
3
|
Income:Unknown
|
|
4
4
|
|
|
5
5
|
2009-12-11 CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
Assets:Bank:Checking -$12.23
|
|
16
16
|
|
|
17
17
|
2009-12-23 CREDIT; Some Company vendorpymt PPD ID: 59728JSL20
|
|
18
|
-
Assets:Bank:Checking $
|
|
18
|
+
Assets:Bank:Checking $3,520.00
|
|
19
19
|
Income:Unknown
|
|
20
20
|
|
|
21
21
|
2009-12-23 CREDIT; Blarg BLARG REVENUE PPD ID: 00jah78563
|
|
22
|
-
Assets:Bank:Checking $
|
|
22
|
+
Assets:Bank:Checking $1,558.52
|
|
23
23
|
Income:Unknown
|
|
24
24
|
|
|
25
25
|
2009-12-24 DEBIT; GITHUB 041287430274 CA 12/22GITHUB 04
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
2009-12-10 CREDIT; Some Company vendorpymt PPD ID: 5KL3832735
|
|
2
|
-
Assets:Bank:Checking $
|
|
2
|
+
Assets:Bank:Checking $2,105.00
|
|
3
3
|
Income:Default
|
|
4
4
|
|
|
5
5
|
2009-12-11 CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
Assets:Bank:Checking -$12.23
|
|
16
16
|
|
|
17
17
|
2009-12-23 CREDIT; Some Company vendorpymt PPD ID: 59728JSL20
|
|
18
|
-
Assets:Bank:Checking $
|
|
18
|
+
Assets:Bank:Checking $3,520.00
|
|
19
19
|
Income:Default
|
|
20
20
|
|
|
21
21
|
2009-12-23 CREDIT; Blarg BLARG REVENUE PPD ID: 00jah78563
|
|
22
|
-
Assets:Bank:Checking $
|
|
22
|
+
Assets:Bank:Checking $1,558.52
|
|
23
23
|
Income:Default
|
|
24
24
|
|
|
25
25
|
2009-12-24 DEBIT; GITHUB 041287430274 CA 12/22GITHUB 04
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
2009-12-10 CREDIT; Some Company vendorpymt PPD ID: 5KL3832735
|
|
2
|
-
Assets:Bank:Checking $
|
|
2
|
+
Assets:Bank:Checking $2,105.00
|
|
3
3
|
Income:Unknown
|
|
4
4
|
|
|
5
5
|
2009-12-11 CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
Assets:Bank:Checking -$12.23
|
|
16
16
|
|
|
17
17
|
2009-12-23 CREDIT; Some Company vendorpymt PPD ID: 59728JSL20
|
|
18
|
-
Assets:Bank:Checking $
|
|
18
|
+
Assets:Bank:Checking $3,520.00
|
|
19
19
|
Income:Unknown
|
|
20
20
|
|
|
21
21
|
2009-12-23 CREDIT; Blarg BLARG REVENUE PPD ID: 00jah78563
|
|
22
|
-
Assets:Bank:Checking $
|
|
22
|
+
Assets:Bank:Checking $1,558.52
|
|
23
23
|
Income:Unknown
|
|
24
24
|
|
|
25
25
|
2009-12-24 DEBIT; GITHUB 041287430274 CA 12/22GITHUB 04
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
2009-12-10 CREDIT; Some Company vendorpymt PPD ID: 5KL3832735
|
|
2
|
-
Assets:Bank:Checking $
|
|
2
|
+
Assets:Bank:Checking $2,105.00
|
|
3
3
|
Income:Unknown
|
|
4
4
|
|
|
5
5
|
2009-12-11 CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
Assets:Bank:Checking -$12.23
|
|
16
16
|
|
|
17
17
|
2009-12-23 CREDIT; Some Company vendorpymt PPD ID: 59728JSL20
|
|
18
|
-
Assets:Bank:Checking $
|
|
18
|
+
Assets:Bank:Checking $3,520.00
|
|
19
19
|
Income:Unknown
|
|
20
20
|
|
|
21
21
|
2009-12-23 CREDIT; Blarg BLARG REVENUE PPD ID: 00jah78563
|
|
22
|
-
Assets:Bank:Checking $
|
|
22
|
+
Assets:Bank:Checking $1,558.52
|
|
23
23
|
Income:Unknown
|
|
24
24
|
|
|
25
25
|
2009-12-24 DEBIT; GITHUB 041287430274 CA 12/22GITHUB 04
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
2009-11-04 TRANSFER CREDIT INTERNET TRANSFER; INTERNET TRANSFER; 1234.00
|
|
2
|
-
Assets:Bank:Checking $
|
|
2
|
+
Assets:Bank:Checking $1,234.00
|
|
3
3
|
Income:Unknown
|
|
4
4
|
|
|
5
5
|
2009-11-10 TRANSFER DEBIT INTERNET TRANSFER; INTERNET TRANSFER MORTGAGE; 0.00
|
|
@@ -16,5 +16,5 @@
|
|
|
16
16
|
|
|
17
17
|
2011-11-04 TRANSFER DEBIT INTERNET TRANSFER; INTERNET TRANSFER SAV TO MECU; 0.00
|
|
18
18
|
Income:Unknown
|
|
19
|
-
Assets:Bank:Checking -$
|
|
19
|
+
Assets:Bank:Checking -$1,234.00
|
|
20
20
|
|
data/spec/integration/test.sh
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
set -Euo pipefail
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|
8
9
|
TEST_DIFF=""
|
|
9
10
|
OUTPUT=""
|
|
10
|
-
RECKON_CMD="
|
|
11
|
+
RECKON_CMD="reckon -v"
|
|
12
|
+
export RUBYLIB=$SCRIPT_DIR/../../lib:${RUBYLIB:-}
|
|
11
13
|
export PATH="$SCRIPT_DIR/../../bin:$PATH"
|
|
12
14
|
|
|
13
15
|
main () {
|
|
@@ -21,16 +23,20 @@ main () {
|
|
|
21
23
|
|
|
22
24
|
echo > test.log
|
|
23
25
|
|
|
26
|
+
NUM_TESTS=$(echo "$TESTS" |wc -l)
|
|
27
|
+
|
|
28
|
+
echo "1..$NUM_TESTS"
|
|
29
|
+
|
|
30
|
+
I=1
|
|
31
|
+
|
|
24
32
|
for t in $TESTS; do
|
|
25
|
-
OUTPUT_FILE=$(mktemp)
|
|
26
33
|
TEST_DIR=$(dirname "$t")
|
|
27
34
|
pushd "$TEST_DIR" >/dev/null || exit 1
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
compare_output "$OUTPUT_FILE"
|
|
35
|
+
if [[ -e "cli_input.exp" ]]; then
|
|
36
|
+
cli_test
|
|
37
|
+
else
|
|
38
|
+
unattended_test
|
|
39
|
+
fi
|
|
34
40
|
|
|
35
41
|
popd >/dev/null || exit 1
|
|
36
42
|
# have to save output after popd
|
|
@@ -38,11 +44,41 @@ main () {
|
|
|
38
44
|
echo -e "TEST_CMD\n$TEST_LOG" >> test.log
|
|
39
45
|
|
|
40
46
|
if [[ $ERROR -ne 0 ]]; then
|
|
47
|
+
echo -e "not ok $I - $TEST_DIR"
|
|
48
|
+
tail -n25 test.log
|
|
41
49
|
exit 1
|
|
50
|
+
else
|
|
51
|
+
echo -e "ok $I - $TEST_DIR"
|
|
42
52
|
fi
|
|
53
|
+
I=$(($I + 1))
|
|
43
54
|
done
|
|
44
55
|
}
|
|
45
56
|
|
|
57
|
+
cli_test () {
|
|
58
|
+
OUTPUT_FILE=$(mktemp)
|
|
59
|
+
TEST_CMD="$RECKON_CMD --table-output-file $OUTPUT_FILE $(cat test_args)"
|
|
60
|
+
TEST_CMD="expect -d -c 'spawn $TEST_CMD' cli_input.exp"
|
|
61
|
+
TEST_LOG=$(eval "$TEST_CMD" 2>&1)
|
|
62
|
+
ERROR=0
|
|
63
|
+
TEST_DIFF=$(diff -u "$OUTPUT_FILE" "expected_output")
|
|
64
|
+
|
|
65
|
+
# ${#} is character length, test that there was no output from diff
|
|
66
|
+
if [ ${#TEST_DIFF} -eq 0 ]; then
|
|
67
|
+
ERROR=0
|
|
68
|
+
else
|
|
69
|
+
ERROR=1
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
unattended_test() {
|
|
74
|
+
OUTPUT_FILE=$(mktemp)
|
|
75
|
+
TEST_CMD="$RECKON_CMD -o $OUTPUT_FILE $(cat test_args)"
|
|
76
|
+
TEST_LOG=$(eval "$TEST_CMD" 2>&1)
|
|
77
|
+
ERROR=0
|
|
78
|
+
|
|
79
|
+
compare_output "$OUTPUT_FILE"
|
|
80
|
+
}
|
|
81
|
+
|
|
46
82
|
test_fail () {
|
|
47
83
|
STATUS=$?
|
|
48
84
|
if [[ $STATUS -ne 0 ]]; then
|
|
@@ -55,7 +91,13 @@ compare_output_for () {
|
|
|
55
91
|
OUTPUT_FILE=$1
|
|
56
92
|
LEDGER=$2
|
|
57
93
|
|
|
58
|
-
|
|
94
|
+
EXPECTED_FILE=$(mktemp)
|
|
95
|
+
ACTUAL_FILE=$(mktemp)
|
|
96
|
+
|
|
97
|
+
$LEDGER -f output.ledger r >"$EXPECTED_FILE" 2>&1 || return 1
|
|
98
|
+
$LEDGER -f output.ledger r >"$ACTUAL_FILE" 2>&1 || return 1
|
|
99
|
+
|
|
100
|
+
TEST_DIFF=$(diff -u "$EXPECTED_FILE" "$ACTUAL_FILE")
|
|
59
101
|
|
|
60
102
|
# ${#} is character length, test that there was no output from diff
|
|
61
103
|
if [ ${#TEST_DIFF} -eq 0 ]; then
|
|
@@ -69,11 +111,9 @@ compare_output () {
|
|
|
69
111
|
OUTPUT_FILE=$1
|
|
70
112
|
|
|
71
113
|
for n in {ledger,hledger}; do
|
|
72
|
-
echo -n " - $n..."
|
|
73
114
|
if compare_output_for "$OUTPUT_FILE" "$n"; then
|
|
74
|
-
|
|
115
|
+
ERROR=0
|
|
75
116
|
else
|
|
76
|
-
echo "FAILED!"
|
|
77
117
|
ERROR=1
|
|
78
118
|
return 0
|
|
79
119
|
fi
|
data/spec/reckon/app_spec.rb
CHANGED
|
@@ -16,7 +16,7 @@ describe Reckon::App do
|
|
|
16
16
|
describe "each_row_backwards" do
|
|
17
17
|
it "should return rows with hashes" do
|
|
18
18
|
@rows[0][:pretty_date].should == "2009-12-10"
|
|
19
|
-
@rows[0][:pretty_money].should == " $
|
|
19
|
+
@rows[0][:pretty_money].should == " $2,105.00"
|
|
20
20
|
@rows[0][:description].should == "CREDIT; Some Company vendorpymt PPD ID: 5KL3832735"
|
|
21
21
|
@rows[1][:pretty_date].should == "2009-12-11"
|
|
22
22
|
@rows[1][:pretty_money].should == " $116.22"
|
|
@@ -242,7 +242,7 @@ describe Reckon::CSVParser do
|
|
|
242
242
|
describe "pretty_money_for" do
|
|
243
243
|
it "work with negative and positive numbers" do
|
|
244
244
|
some_other_bank.pretty_money_for(1).should == "-$20.00"
|
|
245
|
-
some_other_bank.pretty_money_for(4).should == " $
|
|
245
|
+
some_other_bank.pretty_money_for(4).should == " $1,558.52"
|
|
246
246
|
some_other_bank.pretty_money_for(7).should == "-$116.22"
|
|
247
247
|
some_other_bank.pretty_money_for(5).should == " $0.23"
|
|
248
248
|
some_other_bank.pretty_money_for(6).should == "-$0.96"
|
|
@@ -251,7 +251,7 @@ describe Reckon::CSVParser do
|
|
|
251
251
|
it "work with other currencies such as €" do
|
|
252
252
|
euro_bank = Reckon::CSVParser.new(file: fixture_path('some_other.csv'), currency: "€", suffixed: false )
|
|
253
253
|
euro_bank.pretty_money_for(1).should == "-€20.00"
|
|
254
|
-
euro_bank.pretty_money_for(4).should == " €
|
|
254
|
+
euro_bank.pretty_money_for(4).should == " €1,558.52"
|
|
255
255
|
euro_bank.pretty_money_for(7).should == "-€116.22"
|
|
256
256
|
euro_bank.pretty_money_for(5).should == " €0.23"
|
|
257
257
|
euro_bank.pretty_money_for(6).should == "-€0.96"
|
|
@@ -260,7 +260,7 @@ describe Reckon::CSVParser do
|
|
|
260
260
|
it "work with suffixed currencies such as SEK" do
|
|
261
261
|
swedish_bank = Reckon::CSVParser.new(file: fixture_path('some_other.csv'), currency: 'SEK', suffixed: true )
|
|
262
262
|
swedish_bank.pretty_money_for(1).should == "-20.00 SEK"
|
|
263
|
-
swedish_bank.pretty_money_for(4).should == "
|
|
263
|
+
swedish_bank.pretty_money_for(4).should == " 1,558.52 SEK"
|
|
264
264
|
swedish_bank.pretty_money_for(7).should == "-116.22 SEK"
|
|
265
265
|
swedish_bank.pretty_money_for(5).should == " 0.23 SEK"
|
|
266
266
|
swedish_bank.pretty_money_for(6).should == "-0.96 SEK"
|
data/spec/reckon/money_spec.rb
CHANGED
|
@@ -32,17 +32,17 @@ describe Reckon::Money do
|
|
|
32
32
|
describe "pretty" do
|
|
33
33
|
it "work with negative and positive numbers" do
|
|
34
34
|
expect(Reckon::Money.new(-20.00).pretty).to eq("-$20.00")
|
|
35
|
-
expect(Reckon::Money.new(1558.52).pretty).to eq(" $
|
|
35
|
+
expect(Reckon::Money.new(1558.52).pretty).to eq(" $1,558.52")
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
it "work with other currencies such as €" do
|
|
39
39
|
expect(Reckon::Money.new(-20.00, currency: "€", suffixed: false).pretty).to eq("-€20.00")
|
|
40
|
-
expect(Reckon::Money.new(1558.52, currency: "€", suffixed: false).pretty).to eq(" €
|
|
40
|
+
expect(Reckon::Money.new(1558.52, currency: "€", suffixed: false).pretty).to eq(" €1,558.52")
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
it "work with suffixed currencies such as SEK" do
|
|
44
44
|
expect(Reckon::Money.new(-20.00, currency: "SEK", suffixed: true).pretty).to eq("-20.00 SEK")
|
|
45
|
-
expect(Reckon::Money.new(1558.52, currency: "SEK", suffixed: true).pretty).to eq("
|
|
45
|
+
expect(Reckon::Money.new(1558.52, currency: "SEK", suffixed: true).pretty).to eq(" 1,558.52 SEK")
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: reckon
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Cantino
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2021-
|
|
13
|
+
date: 2021-04-22 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rspec
|
|
@@ -130,6 +130,7 @@ files:
|
|
|
130
130
|
- lib/reckon/options.rb
|
|
131
131
|
- lib/reckon/version.rb
|
|
132
132
|
- reckon.gemspec
|
|
133
|
+
- spec/cosine_training_and_test.rb
|
|
133
134
|
- spec/data_fixtures/51-sample.csv
|
|
134
135
|
- spec/data_fixtures/51-tokens.yml
|
|
135
136
|
- spec/data_fixtures/73-sample.csv
|
|
@@ -162,6 +163,10 @@ files:
|
|
|
162
163
|
- spec/integration/another_bank_example/input.csv
|
|
163
164
|
- spec/integration/another_bank_example/output.ledger
|
|
164
165
|
- spec/integration/another_bank_example/test_args
|
|
166
|
+
- spec/integration/ask_for_account/cli_input.exp
|
|
167
|
+
- spec/integration/ask_for_account/expected_output
|
|
168
|
+
- spec/integration/ask_for_account/input.csv
|
|
169
|
+
- spec/integration/ask_for_account/test_args
|
|
165
170
|
- spec/integration/austrian_example/input.csv
|
|
166
171
|
- spec/integration/austrian_example/output.ledger
|
|
167
172
|
- spec/integration/austrian_example/test_args
|