reckon 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +21 -5
- data/Gemfile.lock +1 -45
- data/README.md +0 -10
- data/lib/reckon.rb +1 -2
- data/lib/reckon/app.rb +137 -68
- data/lib/reckon/version.rb +1 -1
- data/reckon.gemspec +1 -3
- data/spec/reckon/app_spec.rb +2 -2
- data/spec/reckon/ledger_parser_spec.rb +2 -2
- metadata +2 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f25c7df49774d944ebc40a73374ac593ebeac2e0b0a201e0d29f9c5ace2642e9
|
4
|
+
data.tar.gz: 27acd960b5210e7e0fb88c50acf35def784411d0b8112f0f0b8e6c4e2f5ab621
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddd5fe0ef08b2718e8083cdbd9695e936737b9ff6b258808787192496675f9a371c302e9936069019821f1c865a3280488aa4396185f1e0bf6e7d84b78dc5c0a
|
7
|
+
data.tar.gz: f611a48dad98a6a4764518dcb2e72969898d6dfbdaf5e06a77f36ab071429ac6f3bd0b0f51200dc8fbaaca913a95519a6bb38e6ec203dc0af61d861802d101f6
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.0.0-p648
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,24 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## [0.
|
3
|
+
## [0.6.0](https://github.com/cantino/reckon/tree/0.6.0) (2020-09-03)
|
4
4
|
|
5
|
-
[Full Changelog](https://github.com/cantino/reckon/compare/v0.5.
|
5
|
+
[Full Changelog](https://github.com/cantino/reckon/compare/v0.5.4...0.6.0)
|
6
|
+
|
7
|
+
**Fixed bugs:**
|
8
|
+
|
9
|
+
- \[BUG\] Reckon appears not to be parsing ISO standard date yyyy-mm-dd? [\#85](https://github.com/cantino/reckon/issues/85)
|
10
|
+
|
11
|
+
**Closed issues:**
|
12
|
+
|
13
|
+
- duplicate detection [\#16](https://github.com/cantino/reckon/issues/16)
|
14
|
+
|
15
|
+
**Merged pull requests:**
|
16
|
+
|
17
|
+
- Add ability to add note to transaction when entering it [\#89](https://github.com/cantino/reckon/pull/89) ([benprew](https://github.com/benprew))
|
18
|
+
|
19
|
+
## [v0.5.4](https://github.com/cantino/reckon/tree/v0.5.4) (2020-06-05)
|
20
|
+
|
21
|
+
[Full Changelog](https://github.com/cantino/reckon/compare/v0.5.3...v0.5.4)
|
6
22
|
|
7
23
|
**Fixed bugs:**
|
8
24
|
|
@@ -36,7 +52,7 @@
|
|
36
52
|
|
37
53
|
**Merged pull requests:**
|
38
54
|
|
39
|
-
-
|
55
|
+
- guard against rows that don't parse dates [\#82](https://github.com/cantino/reckon/pull/82) ([benprew](https://github.com/benprew))
|
40
56
|
|
41
57
|
## [v0.5.0](https://github.com/cantino/reckon/tree/v0.5.0) (2020-02-19)
|
42
58
|
|
@@ -63,7 +79,7 @@
|
|
63
79
|
|
64
80
|
**Merged pull requests:**
|
65
81
|
|
66
|
-
-
|
82
|
+
- Fix bugs in ledger file parsing. Fixes \#56. [\#81](https://github.com/cantino/reckon/pull/81) ([benprew](https://github.com/benprew))
|
67
83
|
- Better file encoding suggestions [\#80](https://github.com/cantino/reckon/pull/80) ([benprew](https://github.com/benprew))
|
68
84
|
- :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))
|
69
85
|
- bug: invalid header lines should be ignored, not parsed. [\#78](https://github.com/cantino/reckon/pull/78) ([benprew](https://github.com/benprew))
|
@@ -182,7 +198,6 @@
|
|
182
198
|
|
183
199
|
**Merged pull requests:**
|
184
200
|
|
185
|
-
- Updated the sources to allow for custom curreny [\#11](https://github.com/cantino/reckon/pull/11) ([ghost](https://github.com/ghost))
|
186
201
|
- Add --account option on the commandline [\#10](https://github.com/cantino/reckon/pull/10) ([copiousfreetime](https://github.com/copiousfreetime))
|
187
202
|
|
188
203
|
## [v0.3.6](https://github.com/cantino/reckon/tree/v0.3.6) (2013-04-30)
|
@@ -216,6 +231,7 @@
|
|
216
231
|
|
217
232
|
**Merged pull requests:**
|
218
233
|
|
234
|
+
- Updated the sources to allow for custom curreny [\#11](https://github.com/cantino/reckon/pull/11) ([ghost](https://github.com/ghost))
|
219
235
|
- adds support for Nordea csv files [\#1](https://github.com/cantino/reckon/pull/1) ([x2q](https://github.com/x2q))
|
220
236
|
|
221
237
|
## [v0.3.3](https://github.com/cantino/reckon/tree/v0.3.3) (2013-01-13)
|
data/Gemfile.lock
CHANGED
@@ -1,58 +1,25 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
reckon (0.
|
4
|
+
reckon (0.6.0)
|
5
5
|
chronic (>= 0.3.0)
|
6
6
|
highline (>= 1.5.2)
|
7
7
|
rchardet (>= 1.8.0)
|
8
|
-
terminal-table (>= 1.4.2)
|
9
8
|
|
10
9
|
GEM
|
11
10
|
remote: http://rubygems.org/
|
12
11
|
specs:
|
13
|
-
activesupport (6.0.3.1)
|
14
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
|
-
i18n (>= 0.7, < 2)
|
16
|
-
minitest (~> 5.1)
|
17
|
-
tzinfo (~> 1.1)
|
18
|
-
zeitwerk (~> 2.2, >= 2.2.2)
|
19
|
-
addressable (2.7.0)
|
20
|
-
public_suffix (>= 2.0.2, < 5.0)
|
21
12
|
chronic (0.10.2)
|
22
13
|
coderay (1.1.2)
|
23
|
-
concurrent-ruby (1.1.6)
|
24
14
|
diff-lcs (1.3)
|
25
|
-
faraday (1.0.1)
|
26
|
-
multipart-post (>= 1.2, < 3)
|
27
|
-
faraday-http-cache (2.2.0)
|
28
|
-
faraday (>= 0.8)
|
29
|
-
github_changelog_generator (1.15.2)
|
30
|
-
activesupport
|
31
|
-
faraday-http-cache
|
32
|
-
multi_json
|
33
|
-
octokit (~> 4.6)
|
34
|
-
rainbow (>= 2.2.1)
|
35
|
-
rake (>= 10.0)
|
36
|
-
retriable (~> 3.0)
|
37
15
|
highline (2.0.3)
|
38
|
-
i18n (1.8.2)
|
39
|
-
concurrent-ruby (~> 1.0)
|
40
16
|
method_source (0.9.2)
|
41
|
-
minitest (5.14.1)
|
42
|
-
multi_json (1.14.1)
|
43
|
-
multipart-post (2.1.1)
|
44
|
-
octokit (4.18.0)
|
45
|
-
faraday (>= 0.9)
|
46
|
-
sawyer (~> 0.8.0, >= 0.5.3)
|
47
17
|
pry (0.12.2)
|
48
18
|
coderay (~> 1.1.0)
|
49
19
|
method_source (~> 0.9.0)
|
50
|
-
public_suffix (4.0.5)
|
51
|
-
rainbow (3.0.0)
|
52
20
|
rake (12.3.3)
|
53
21
|
rantly (1.2.0)
|
54
22
|
rchardet (1.8.0)
|
55
|
-
retriable (3.1.2)
|
56
23
|
rspec (3.9.0)
|
57
24
|
rspec-core (~> 3.9.0)
|
58
25
|
rspec-expectations (~> 3.9.0)
|
@@ -66,22 +33,11 @@ GEM
|
|
66
33
|
diff-lcs (>= 1.2.0, < 2.0)
|
67
34
|
rspec-support (~> 3.9.0)
|
68
35
|
rspec-support (3.9.2)
|
69
|
-
sawyer (0.8.2)
|
70
|
-
addressable (>= 2.3.5)
|
71
|
-
faraday (> 0.8, < 2.0)
|
72
|
-
terminal-table (1.8.0)
|
73
|
-
unicode-display_width (~> 1.1, >= 1.1.1)
|
74
|
-
thread_safe (0.3.6)
|
75
|
-
tzinfo (1.2.7)
|
76
|
-
thread_safe (~> 0.1)
|
77
|
-
unicode-display_width (1.7.0)
|
78
|
-
zeitwerk (2.3.0)
|
79
36
|
|
80
37
|
PLATFORMS
|
81
38
|
ruby
|
82
39
|
|
83
40
|
DEPENDENCIES
|
84
|
-
github_changelog_generator
|
85
41
|
pry (>= 0.12.2)
|
86
42
|
rake
|
87
43
|
rantly (= 1.2.0)
|
data/README.md
CHANGED
@@ -114,13 +114,3 @@ You can override them with `--default_outof_account` and `--default_into_account
|
|
114
114
|
Copyright (c) 2013 Andrew Cantino. See LICENSE for details.
|
115
115
|
|
116
116
|
Thanks to @BlackEdder for many contributions!
|
117
|
-
|
118
|
-
## Building a new version of reckon
|
119
|
-
1. Update reckon/version.rb
|
120
|
-
2. Run `bundle install` to build updated Gemfile.lock
|
121
|
-
3. Run `bundle exec github_changelog_generator -u cantino -p reckon -t $TOKEN --future-release $VERSION`
|
122
|
-
3. Commit changes with: 'Release $VERSION'
|
123
|
-
4. Tag release `git tag v$VERSION`
|
124
|
-
5. `git push && git push --tags`
|
125
|
-
6. Build new gem `gem build reckon.gemspec`
|
126
|
-
7. Push new gem `gem push <gemname>`
|
data/lib/reckon.rb
CHANGED
data/lib/reckon/app.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
|
2
3
|
require 'pp'
|
3
4
|
require 'yaml'
|
4
5
|
|
5
6
|
module Reckon
|
6
7
|
class App
|
7
8
|
attr_accessor :options, :seen, :csv_parser, :regexps, :matcher
|
9
|
+
@@cli = HighLine.new
|
8
10
|
|
9
11
|
def initialize(options = {})
|
10
12
|
LOGGER.level = Logger::INFO if options[:verbose]
|
11
13
|
self.options = options
|
12
14
|
self.regexps = {}
|
13
|
-
self.seen =
|
15
|
+
self.seen = Set.new
|
14
16
|
self.options[:currency] ||= '$'
|
15
|
-
options[:string] = File.read(options[:file]) unless options[:string]
|
16
17
|
@csv_parser = CSVParser.new( options )
|
17
18
|
@matcher = CosineSimilarity.new(options)
|
18
19
|
learn!
|
@@ -20,22 +21,19 @@ module Reckon
|
|
20
21
|
|
21
22
|
def interactive_output(str)
|
22
23
|
return if options[:unattended]
|
24
|
+
|
23
25
|
puts str
|
24
26
|
end
|
25
27
|
|
26
28
|
def learn!
|
27
29
|
learn_from_account_tokens(options[:account_tokens_file])
|
28
|
-
|
29
|
-
ledger_file = options[:existing_ledger_file]
|
30
|
-
return unless ledger_file
|
31
|
-
fail "#{ledger_file} doesn't exist!" unless File.exists?(ledger_file)
|
32
|
-
learn_from(File.read(ledger_file))
|
30
|
+
learn_from_ledger_file(options[:existing_ledger_file])
|
33
31
|
end
|
34
32
|
|
35
33
|
def learn_from_account_tokens(filename)
|
36
34
|
return unless filename
|
37
35
|
|
38
|
-
|
36
|
+
raise "#{filename} doesn't exist!" unless File.exist?(filename)
|
39
37
|
|
40
38
|
extract_account_tokens(YAML.load_file(filename)).each do |account, tokens|
|
41
39
|
tokens.each do |t|
|
@@ -48,14 +46,27 @@ module Reckon
|
|
48
46
|
end
|
49
47
|
end
|
50
48
|
|
51
|
-
def
|
49
|
+
def learn_from_ledger_file(ledger_file)
|
50
|
+
return unless ledger_file
|
51
|
+
|
52
|
+
raise "#{ledger_file} doesn't exist!" unless File.exist?(ledger_file)
|
53
|
+
|
54
|
+
learn_from_ledger(File.read(ledger_file))
|
55
|
+
end
|
56
|
+
|
57
|
+
def learn_from_ledger(ledger)
|
58
|
+
LOGGER.info "learning from #{ledger}"
|
52
59
|
LedgerParser.new(ledger).entries.each do |entry|
|
53
60
|
entry[:accounts].each do |account|
|
54
61
|
str = [entry[:desc], account[:amount]].join(" ")
|
55
|
-
|
62
|
+
if account[:name] != options[:bank_account]
|
63
|
+
LOGGER.info "adding document #{account[:name]} #{str}"
|
64
|
+
@matcher.add_document(account[:name], str)
|
65
|
+
end
|
56
66
|
pretty_date = entry[:date].iso8601
|
57
|
-
|
58
|
-
|
67
|
+
if account[:name] == options[:bank_account]
|
68
|
+
seen << seen_key(pretty_date, @csv_parser.pretty_money(account[:amount]))
|
69
|
+
end
|
59
70
|
end
|
60
71
|
end
|
61
72
|
end
|
@@ -91,9 +102,10 @@ module Reckon
|
|
91
102
|
end
|
92
103
|
|
93
104
|
def walk_backwards
|
105
|
+
cmd_options = "[account]/[q]uit/[s]kip/[n]ote/[d]escription"
|
94
106
|
seen_anything_new = false
|
95
107
|
each_row_backwards do |row|
|
96
|
-
|
108
|
+
print_transaction([row])
|
97
109
|
|
98
110
|
if already_seen?(row)
|
99
111
|
interactive_output "NOTE: This row is very similar to a previous one!"
|
@@ -105,50 +117,28 @@ module Reckon
|
|
105
117
|
seen_anything_new = true
|
106
118
|
end
|
107
119
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
else
|
114
|
-
out_of_account = ask("Which account provided this income? ([account]/[q]uit/[s]kip) ") { |q|
|
115
|
-
q.completion = possible_answers
|
116
|
-
q.readline = true
|
117
|
-
q.default = possible_answers.first
|
118
|
-
}
|
119
|
-
end
|
120
|
-
|
121
|
-
finish if out_of_account == "quit" || out_of_account == "q"
|
122
|
-
if out_of_account == "skip" || out_of_account == "s"
|
123
|
-
interactive_output "Skipping"
|
124
|
-
next
|
125
|
-
end
|
126
|
-
|
127
|
-
ledger_format( row,
|
128
|
-
[options[:bank_account], row[:pretty_money]],
|
129
|
-
[out_of_account, row[:pretty_money_negated]] )
|
120
|
+
if row[:money] > 0
|
121
|
+
# out_of_account
|
122
|
+
answer = ask_account_question("Which account provided this income? (#{cmd_options})", row)
|
123
|
+
line1 = [options[:bank_account], row[:pretty_money]]
|
124
|
+
line2 = [answer, ""]
|
130
125
|
else
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
q.default = possible_answers.first
|
138
|
-
}
|
139
|
-
end
|
140
|
-
finish if into_account == "quit" || into_account == 'q'
|
141
|
-
if into_account == "skip" || into_account == 's'
|
142
|
-
interactive_output "Skipping"
|
143
|
-
next
|
144
|
-
end
|
126
|
+
# into_account
|
127
|
+
answer = ask_account_question("To which account did this money go? (#{cmd_options})", row)
|
128
|
+
# line1 = [answer, row[:pretty_money_negated]]
|
129
|
+
line1 = [answer, ""]
|
130
|
+
line2 = [options[:bank_account], row[:pretty_money]]
|
131
|
+
end
|
145
132
|
|
146
|
-
|
147
|
-
|
148
|
-
|
133
|
+
finish if %w[quit q].include?(answer)
|
134
|
+
if %w[skip s].include?(answer)
|
135
|
+
interactive_output "Skipping"
|
136
|
+
next
|
149
137
|
end
|
150
138
|
|
151
|
-
|
139
|
+
ledger = ledger_format(row, line1, line2)
|
140
|
+
LOGGER.info "ledger line: #{ledger}"
|
141
|
+
learn_from_ledger(ledger) unless options[:account_tokens_file]
|
152
142
|
output(ledger)
|
153
143
|
end
|
154
144
|
end
|
@@ -167,16 +157,93 @@ module Reckon
|
|
167
157
|
:money => @csv_parser.money_for(index),
|
168
158
|
:description => @csv_parser.description_for(index) }
|
169
159
|
end
|
170
|
-
rows.sort_by { |n| n[:date] }.each {|row| yield row }
|
160
|
+
rows.sort_by { |n| n[:date] }.each { |row| yield row }
|
161
|
+
end
|
162
|
+
|
163
|
+
def print_transaction(rows)
|
164
|
+
str = "\n"
|
165
|
+
header = %w[Date Amount Description Note]
|
166
|
+
maxes = header.map(&:length)
|
167
|
+
|
168
|
+
rows = rows.map { |r| [r[:pretty_date], r[:pretty_money], r[:description], r[:note]] }
|
169
|
+
|
170
|
+
rows.each do |r|
|
171
|
+
r.length.times { |i| l = r[i] ? r[i].length : 0; maxes[i] = l if maxes[i] < l }
|
172
|
+
end
|
173
|
+
|
174
|
+
header.each_with_index do |n, i|
|
175
|
+
str += " #{n.center(maxes[i])} |"
|
176
|
+
end
|
177
|
+
str += "\n"
|
178
|
+
|
179
|
+
rows.each do |row|
|
180
|
+
row.each_with_index do |_, i|
|
181
|
+
just = maxes[i]
|
182
|
+
str += sprintf(" %#{just}s |", row[i])
|
183
|
+
end
|
184
|
+
str += "\n"
|
185
|
+
end
|
186
|
+
|
187
|
+
interactive_output str
|
188
|
+
end
|
189
|
+
|
190
|
+
def ask_account_question(msg, row)
|
191
|
+
possible_answers = suggest(row)
|
192
|
+
LOGGER.info "possible_answers===> #{possible_answers.inspect}"
|
193
|
+
|
194
|
+
if options[:unattended]
|
195
|
+
default = if row[:pretty_money][0] == '-'
|
196
|
+
options[:default_into_account] || 'Expenses:Unknown'
|
197
|
+
else
|
198
|
+
options[:default_outof_account] || 'Income:Unknown'
|
199
|
+
end
|
200
|
+
return possible_answers[0] || default
|
201
|
+
end
|
202
|
+
|
203
|
+
answer = @@cli.ask(msg) do |q|
|
204
|
+
q.completion = possible_answers
|
205
|
+
q.readline = true
|
206
|
+
q.default = possible_answers.first
|
207
|
+
end
|
208
|
+
|
209
|
+
# if answer isn't n/note/d/description, must be an account name, or skip, or quit
|
210
|
+
return answer unless %w[n note d description].include?(answer)
|
211
|
+
|
212
|
+
add_description(row) if %w[d description].include?(answer)
|
213
|
+
add_note(row) if %w[n note].include?(answer)
|
214
|
+
|
215
|
+
print_transaction([row])
|
216
|
+
# give user a chance to set account name or retry description
|
217
|
+
return ask_account_question(msg, row)
|
218
|
+
end
|
219
|
+
|
220
|
+
def add_description(row)
|
221
|
+
desc_answer = @@cli.ask("Enter a new description for this transaction (empty line aborts)\n") do |q|
|
222
|
+
q.overwrite = true
|
223
|
+
q.readline = true
|
224
|
+
q.default = row[:description]
|
225
|
+
end
|
226
|
+
|
227
|
+
row[:description] = desc_answer unless desc_answer.empty?
|
228
|
+
end
|
229
|
+
|
230
|
+
def add_note(row)
|
231
|
+
desc_answer = @@cli.ask("Enter a new note for this transaction (empty line aborts)\n") do |q|
|
232
|
+
q.overwrite = true
|
233
|
+
q.readline = true
|
234
|
+
q.default = row[:note]
|
235
|
+
end
|
236
|
+
|
237
|
+
row[:note] = desc_answer unless desc_answer.empty?
|
171
238
|
end
|
172
239
|
|
173
|
-
def most_specific_regexp_match(
|
240
|
+
def most_specific_regexp_match(row)
|
174
241
|
matches = regexps.map { |regexp, account|
|
175
242
|
if match = regexp.match(row[:description])
|
176
243
|
[account, match[0]]
|
177
244
|
end
|
178
245
|
}.compact
|
179
|
-
matches.sort_by! { |
|
246
|
+
matches.sort_by! { |_account, matched_text| matched_text.length }.map(&:first)
|
180
247
|
end
|
181
248
|
|
182
249
|
def suggest(row)
|
@@ -185,9 +252,9 @@ module Reckon
|
|
185
252
|
end
|
186
253
|
|
187
254
|
def ledger_format(row, line1, line2)
|
188
|
-
out = "#{row[:pretty_date]}\t#{row[:description]}\n"
|
189
|
-
out += "\t#{line1.first}\t\t\t
|
190
|
-
out += "\t#{line2.first}\t\t\t
|
255
|
+
out = "#{row[:pretty_date]}\t#{row[:description]}\t; #{row[:note]}\n"
|
256
|
+
out += "\t#{line1.first}\t\t\t#{line1.last}\n"
|
257
|
+
out += "\t#{line2.first}\t\t\t#{line2.last}\n\n"
|
191
258
|
out
|
192
259
|
end
|
193
260
|
|
@@ -196,8 +263,12 @@ module Reckon
|
|
196
263
|
options[:output_file].flush
|
197
264
|
end
|
198
265
|
|
266
|
+
def seen_key(date, amount)
|
267
|
+
return [date, amount].join("|")
|
268
|
+
end
|
269
|
+
|
199
270
|
def already_seen?(row)
|
200
|
-
seen
|
271
|
+
seen.include?(seen_key(row[:pretty_date], row[:pretty_money]))
|
201
272
|
end
|
202
273
|
|
203
274
|
def finish
|
@@ -207,13 +278,11 @@ module Reckon
|
|
207
278
|
end
|
208
279
|
|
209
280
|
def output_table
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
t << [ row[:pretty_date], row[:pretty_money], row[:description] ]
|
214
|
-
end
|
281
|
+
rows = []
|
282
|
+
each_row_backwards do |row|
|
283
|
+
rows << row
|
215
284
|
end
|
216
|
-
|
285
|
+
print_transaction(rows)
|
217
286
|
end
|
218
287
|
|
219
288
|
def self.parse_opts(args = ARGV)
|
@@ -321,7 +390,7 @@ module Reckon
|
|
321
390
|
end
|
322
391
|
|
323
392
|
unless options[:file]
|
324
|
-
options[:file] = ask("What CSV file should I parse? ")
|
393
|
+
options[:file] = @@cli.ask("What CSV file should I parse? ")
|
325
394
|
unless options[:file].length > 0
|
326
395
|
puts "\nYou must provide a CSV file to parse.\n"
|
327
396
|
puts parser
|
@@ -332,7 +401,7 @@ module Reckon
|
|
332
401
|
unless options[:bank_account]
|
333
402
|
fail "Please specify --account for the unattended mode" if options[:unattended]
|
334
403
|
|
335
|
-
options[:bank_account] = ask("What is the account name of this bank account in Ledger? ") do |q|
|
404
|
+
options[:bank_account] = @@cli.ask("What is the account name of this bank account in Ledger? ") do |q|
|
336
405
|
q.readline = true
|
337
406
|
q.validate = /^.{2,}$/
|
338
407
|
q.default = "Assets:Bank:Checking"
|
data/lib/reckon/version.rb
CHANGED
data/reckon.gemspec
CHANGED
@@ -13,15 +13,13 @@ Gem::Specification.new do |s|
|
|
13
13
|
|
14
14
|
s.files = `git ls-files`.split("\n")
|
15
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
19
|
s.add_development_dependency "rspec", ">= 1.2.9"
|
20
20
|
s.add_development_dependency "pry", ">= 0.12.2"
|
21
21
|
s.add_development_dependency "rantly", "= 1.2.0"
|
22
|
-
s.add_development_dependency "github_changelog_generator"
|
23
22
|
s.add_runtime_dependency "chronic", ">= 0.3.0"
|
24
23
|
s.add_runtime_dependency "highline", ">= 1.5.2"
|
25
|
-
s.add_runtime_dependency "terminal-table", ">= 1.4.2"
|
26
24
|
s.add_runtime_dependency "rchardet", ">= 1.8.0"
|
27
25
|
end
|
data/spec/reckon/app_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Reckon::App do
|
|
8
8
|
context 'with chase csv input' do
|
9
9
|
before do
|
10
10
|
@chase = Reckon::App.new(string: BANK_CSV)
|
11
|
-
@chase.
|
11
|
+
@chase.learn_from_ledger(BANK_LEDGER)
|
12
12
|
@rows = []
|
13
13
|
@chase.each_row_backwards { |row| @rows.push(row) }
|
14
14
|
end
|
@@ -68,7 +68,7 @@ describe Reckon::App do
|
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'should learn from a ledger file' do
|
71
|
-
chase.
|
71
|
+
chase.learn_from_ledger(BANK_LEDGER)
|
72
72
|
chase.walk_backwards
|
73
73
|
output_file.string.scan('Expenses:Books').count.should == 1
|
74
74
|
end
|
@@ -58,10 +58,10 @@ describe Reckon::LedgerParser do
|
|
58
58
|
headers = %w[date code desc name currency amount type commend]
|
59
59
|
safe_s = Shellwords.escape(s)
|
60
60
|
|
61
|
-
lp_csv = Reckon::LedgerParser.new(s, date_format: '%Y
|
61
|
+
lp_csv = Reckon::LedgerParser.new(s, date_format: '%Y/%m/%d').to_csv.join("\n")
|
62
62
|
actual = CSV.parse(lp_csv, headers: headers).map(&filter_format)
|
63
63
|
|
64
|
-
ledger_csv = `echo #{safe_s} | ledger csv --date-format '%Y
|
64
|
+
ledger_csv = `echo #{safe_s} | ledger csv --date-format '%Y/%m/%d' -f - `
|
65
65
|
expected = CSV.parse(ledger_csv.gsub('\"', '""'), headers: headers).map(&filter_format)
|
66
66
|
expected.length.times do |i|
|
67
67
|
expect(actual[i]).to eq(expected[i])
|
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.
|
4
|
+
version: 0.6.0
|
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: 2020-
|
13
|
+
date: 2020-09-04 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -54,20 +54,6 @@ dependencies:
|
|
54
54
|
- - '='
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: 1.2.0
|
57
|
-
- !ruby/object:Gem::Dependency
|
58
|
-
name: github_changelog_generator
|
59
|
-
requirement: !ruby/object:Gem::Requirement
|
60
|
-
requirements:
|
61
|
-
- - ">="
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: '0'
|
64
|
-
type: :development
|
65
|
-
prerelease: false
|
66
|
-
version_requirements: !ruby/object:Gem::Requirement
|
67
|
-
requirements:
|
68
|
-
- - ">="
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
version: '0'
|
71
57
|
- !ruby/object:Gem::Dependency
|
72
58
|
name: chronic
|
73
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,20 +82,6 @@ dependencies:
|
|
96
82
|
- - ">="
|
97
83
|
- !ruby/object:Gem::Version
|
98
84
|
version: 1.5.2
|
99
|
-
- !ruby/object:Gem::Dependency
|
100
|
-
name: terminal-table
|
101
|
-
requirement: !ruby/object:Gem::Requirement
|
102
|
-
requirements:
|
103
|
-
- - ">="
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
version: 1.4.2
|
106
|
-
type: :runtime
|
107
|
-
prerelease: false
|
108
|
-
version_requirements: !ruby/object:Gem::Requirement
|
109
|
-
requirements:
|
110
|
-
- - ">="
|
111
|
-
- !ruby/object:Gem::Version
|
112
|
-
version: 1.4.2
|
113
85
|
- !ruby/object:Gem::Dependency
|
114
86
|
name: rchardet
|
115
87
|
requirement: !ruby/object:Gem::Requirement
|