reckon 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|