reckon 0.9.6 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -0
- data/CHANGELOG.md +26 -0
- data/Gemfile.lock +2 -2
- data/README.md +7 -0
- data/lib/reckon/app.rb +51 -9
- data/lib/reckon/cosine_similarity.rb +1 -0
- data/lib/reckon/csv_parser.rb +9 -8
- data/lib/reckon/ledger_parser.rb +1 -1
- data/lib/reckon/logger.rb +4 -0
- data/lib/reckon/options.rb +39 -9
- data/lib/reckon/version.rb +1 -1
- data/spec/cosine_training_and_test.rb +2 -1
- data/spec/integration/ask_for_account/expected_output +10 -10
- data/spec/integration/unattended_config/input.csv +9 -0
- data/spec/integration/unattended_config/output.ledger +36 -0
- data/spec/integration/unattended_config/test_args +2 -0
- data/spec/integration/unattended_config/tokens.yml +19 -0
- data/spec/reckon/ledger_parser_spec.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58ef387a88fd33e7aeddc98842e3c5cf147e74830b659393ec5f75d0179d6bba
|
4
|
+
data.tar.gz: 3983fafdcce5b9e016dfd09cfa7a905bc0bf829d3b15f383f162b5738bbf0f49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44731aea841dc2c3a4830085eda5dccc3b8958502eb21b8aee7ea4d52f2429e7dc2125de4c15084c804970ebc1199a859ef87437518f9635d0f8c33ae7c4444c
|
7
|
+
data.tar.gz: c2f4ed1e9ccf0f169a285d5337b3f97b7867d018a8541f4c009fe4dc105f0141884066071860a68b9baf688452b44ccc34b109d6ad4ff576645213c0ece3019e
|
data/.rubocop.yml
CHANGED
@@ -18,3 +18,15 @@ Metrics/AbcSize:
|
|
18
18
|
|
19
19
|
Style/NumericPredicate:
|
20
20
|
Enabled: False
|
21
|
+
|
22
|
+
Metrics/PerceivedComplexity:
|
23
|
+
Enabled: False
|
24
|
+
|
25
|
+
Metrics/CyclomaticComplexity:
|
26
|
+
Enabled: False
|
27
|
+
|
28
|
+
Style/FormatString:
|
29
|
+
Enabled: False
|
30
|
+
|
31
|
+
Naming/MethodParameterName:
|
32
|
+
Enabled: False
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v0.11.0](https://github.com/cantino/reckon/tree/v0.11.0) (2025-03-04)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/cantino/reckon/compare/v0.10.0...v0.11.0)
|
6
|
+
|
7
|
+
**Closed issues:**
|
8
|
+
|
9
|
+
- Feature request: confidence score [\#134](https://github.com/cantino/reckon/issues/134)
|
10
|
+
- feature request [\#133](https://github.com/cantino/reckon/issues/133)
|
11
|
+
|
12
|
+
## [v0.10.0](https://github.com/cantino/reckon/tree/v0.10.0) (2024-11-27)
|
13
|
+
|
14
|
+
[Full Changelog](https://github.com/cantino/reckon/compare/v0.9.6...v0.10.0)
|
15
|
+
|
16
|
+
**Closed issues:**
|
17
|
+
|
18
|
+
- Is it possible to use reckon with only no info about incoming or going out? [\#131](https://github.com/cantino/reckon/issues/131)
|
19
|
+
- Reckon fails immediately with error about uninitialized constant `Readline` [\#129](https://github.com/cantino/reckon/issues/129)
|
20
|
+
|
21
|
+
## [v0.9.6](https://github.com/cantino/reckon/tree/v0.9.6) (2024-03-27)
|
22
|
+
|
23
|
+
[Full Changelog](https://github.com/cantino/reckon/compare/v0.9.5...v0.9.6)
|
24
|
+
|
25
|
+
**Closed issues:**
|
26
|
+
|
27
|
+
- reckon can't learn from a file with the "wrong" date format [\#130](https://github.com/cantino/reckon/issues/130)
|
28
|
+
|
3
29
|
## [v0.9.5](https://github.com/cantino/reckon/tree/v0.9.5) (2024-01-08)
|
4
30
|
|
5
31
|
[Full Changelog](https://github.com/cantino/reckon/compare/v0.9.4...v0.9.5)
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
reckon (0.
|
4
|
+
reckon (0.11.0)
|
5
5
|
chronic (>= 0.3.0)
|
6
6
|
highline (~> 2.0)
|
7
7
|
matrix (>= 0.4.2)
|
@@ -21,7 +21,7 @@ GEM
|
|
21
21
|
method_source (~> 1.0)
|
22
22
|
rake (13.0.6)
|
23
23
|
rantly (1.2.0)
|
24
|
-
rchardet (1.
|
24
|
+
rchardet (1.9.0)
|
25
25
|
rspec (3.12.0)
|
26
26
|
rspec-core (~> 3.12.0)
|
27
27
|
rspec-expectations (~> 3.12.0)
|
data/README.md
CHANGED
@@ -49,6 +49,8 @@ Learn more:
|
|
49
49
|
Column number of the money columns, starts from 1 (1 or 2 columns)
|
50
50
|
--raw-money
|
51
51
|
Don't format money column (for stocks)
|
52
|
+
--sort DATE|DESC|AMT
|
53
|
+
Sort file by date, description, or amount
|
52
54
|
--date-column 3
|
53
55
|
Column number of the date column, starts from 1
|
54
56
|
--contains-header [N]
|
@@ -106,6 +108,9 @@ Would tokenize to 'ING', 'Direct' and 'Deposit'. The matcher would then suggest
|
|
106
108
|
Here's an example of `tokens.yaml`:
|
107
109
|
|
108
110
|
```
|
111
|
+
config:
|
112
|
+
similarity_threshold: 2 # range 0-10
|
113
|
+
|
109
114
|
Income:
|
110
115
|
Salary:
|
111
116
|
- 'LÖN'
|
@@ -124,6 +129,8 @@ Expenses:
|
|
124
129
|
|
125
130
|
Reckon will use `Income:Unknown` or `Expenses:Unknown` if it can't match a transaction to an account.
|
126
131
|
|
132
|
+
The config key is a special key used to set configuration when running in unattended mode. The only config variable is similarity_threshold (currently).
|
133
|
+
|
127
134
|
You can override these names with the `--default_outof_account` and `--default_into_account` options.
|
128
135
|
|
129
136
|
### Substring Match
|
data/lib/reckon/app.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require 'yaml'
|
4
4
|
require 'stringio'
|
5
5
|
|
6
|
+
UnattendedConfig = Struct.new(:similarity_threshold)
|
7
|
+
|
6
8
|
module Reckon
|
7
9
|
# The main app
|
8
10
|
class App
|
@@ -10,10 +12,11 @@ module Reckon
|
|
10
12
|
|
11
13
|
def initialize(opts = {})
|
12
14
|
self.options = opts
|
13
|
-
LOGGER.level =
|
15
|
+
LOGGER.level = options[:verbose] || Logger::WARN
|
14
16
|
|
15
17
|
self.regexps = {}
|
16
18
|
self.seen = Set.new
|
19
|
+
options[:sort] ||= :date
|
17
20
|
@cli = HighLine.new
|
18
21
|
@csv_parser = CSVParser.new(options)
|
19
22
|
@matcher = CosineSimilarity.new(options)
|
@@ -41,7 +44,11 @@ module Reckon
|
|
41
44
|
|
42
45
|
raise "#{filename} doesn't exist!" unless File.exist?(filename)
|
43
46
|
|
44
|
-
|
47
|
+
tokens = YAML.load_file(filename)
|
48
|
+
cfg = build_unattended_config(tokens.delete('config'))
|
49
|
+
@options[:similarity_threshold] = cfg.similarity_threshold if cfg
|
50
|
+
|
51
|
+
extract_account_tokens(tokens).each do |account, tokens|
|
45
52
|
tokens.each do |t|
|
46
53
|
if t.start_with?('/')
|
47
54
|
add_regexp(account, t)
|
@@ -52,6 +59,13 @@ module Reckon
|
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
62
|
+
def build_unattended_config(cfg)
|
63
|
+
return unless cfg
|
64
|
+
invalid = cfg.keys - UnattendedConfig.members.map(&:to_s)
|
65
|
+
raise "Invalid keys in config: #{invalid}" if invalid.any?
|
66
|
+
return UnattendedConfig.new(*cfg.values_at(*UnattendedConfig.members.map(&:to_s)))
|
67
|
+
end
|
68
|
+
|
55
69
|
def learn_from_ledger_file(ledger_file)
|
56
70
|
return unless ledger_file
|
57
71
|
|
@@ -80,7 +94,7 @@ module Reckon
|
|
80
94
|
|
81
95
|
# Add tokens from account_tokens_file to accounts
|
82
96
|
def extract_account_tokens(subtree, account = nil)
|
83
|
-
if subtree.nil?
|
97
|
+
if subtree.nil? || !subtree
|
84
98
|
puts "Warning: empty #{account} tree"
|
85
99
|
{}
|
86
100
|
elsif subtree.is_a?(Array)
|
@@ -141,6 +155,11 @@ module Reckon
|
|
141
155
|
line2 = [options[:bank_account], row[:pretty_money]]
|
142
156
|
end
|
143
157
|
|
158
|
+
if answer == '~~SKIP~~'
|
159
|
+
LOGGER.info "skipping transaction: #{row}"
|
160
|
+
next
|
161
|
+
end
|
162
|
+
|
144
163
|
finish if %w[quit q].include?(answer)
|
145
164
|
if %w[skip s].include?(answer)
|
146
165
|
interactive_output "Skipping"
|
@@ -168,18 +187,29 @@ module Reckon
|
|
168
187
|
:money => @csv_parser.money_for(index),
|
169
188
|
:description => @csv_parser.description_for(index) }
|
170
189
|
end
|
171
|
-
rows.sort_by
|
190
|
+
rows.sort_by do |n|
|
191
|
+
[n[options[:sort]], -n[:money], n[:description]]
|
192
|
+
end.each do |row|
|
193
|
+
yield row
|
194
|
+
end
|
172
195
|
end
|
173
196
|
|
174
197
|
def print_transaction(rows, fh = $stdout)
|
175
198
|
str = "\n"
|
176
|
-
header = %w[Date Amount Description
|
199
|
+
header = %w[Date Amount Description]
|
200
|
+
header += ["Note"] if rows.map { |r| r[:note] }.any?
|
177
201
|
maxes = header.map(&:length)
|
178
|
-
|
179
|
-
|
202
|
+
rows = rows.map do |r|
|
203
|
+
[r[:pretty_date], r[:pretty_money], r[:description], r[:note]].compact
|
204
|
+
end
|
180
205
|
|
181
206
|
rows.each do |r|
|
182
|
-
r.length.times
|
207
|
+
r.length.times do |i|
|
208
|
+
l = 0
|
209
|
+
l = r[i].length if r[i]
|
210
|
+
maxes[i] ||= 0
|
211
|
+
maxes[i] = l if maxes[i] < l
|
212
|
+
end
|
183
213
|
end
|
184
214
|
|
185
215
|
header.each_with_index do |n, i|
|
@@ -199,6 +229,15 @@ module Reckon
|
|
199
229
|
end
|
200
230
|
|
201
231
|
def ask_account_question(msg, row)
|
232
|
+
# return account token if it matches
|
233
|
+
token_answer = most_specific_regexp_match(row)
|
234
|
+
if token_answer.any?
|
235
|
+
row[:note] = "Matched account token"
|
236
|
+
puts "NOTE: Matched account token"
|
237
|
+
puts token_answer[0]
|
238
|
+
return token_answer[0]
|
239
|
+
end
|
240
|
+
|
202
241
|
possible_answers = suggest(row)
|
203
242
|
LOGGER.info "possible_answers===> #{possible_answers.inspect}"
|
204
243
|
|
@@ -261,7 +300,10 @@ module Reckon
|
|
261
300
|
|
262
301
|
def suggest(row)
|
263
302
|
most_specific_regexp_match(row) +
|
264
|
-
@matcher.find_similar(row[:description]).
|
303
|
+
@matcher.find_similar(row[:description]).filter do |n|
|
304
|
+
!@options[:similarity_threshold] ||
|
305
|
+
n.fetch(:simliarity, 0) * 10 >= @options[:similarity_threshold]
|
306
|
+
end.map { |n| n[:account] }
|
265
307
|
end
|
266
308
|
|
267
309
|
def output(ledger_line)
|
data/lib/reckon/csv_parser.rb
CHANGED
@@ -64,13 +64,13 @@ module Reckon
|
|
64
64
|
private
|
65
65
|
|
66
66
|
def filter_csv
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
@columns = new_columns
|
67
|
+
return unless options[:ignore_columns]
|
68
|
+
|
69
|
+
new_columns = []
|
70
|
+
columns.each_with_index do |column, index|
|
71
|
+
new_columns << (options[:ignore_columns].include?(index + 1) ? [''] * column.length : column)
|
73
72
|
end
|
73
|
+
@columns = new_columns
|
74
74
|
end
|
75
75
|
|
76
76
|
def evaluate_columns(cols)
|
@@ -222,7 +222,8 @@ module Reckon
|
|
222
222
|
# convert to a stringio object to handle multi-line fields
|
223
223
|
parser_opts = {
|
224
224
|
col_sep: separator,
|
225
|
-
skip_blanks: true
|
225
|
+
skip_blanks: true,
|
226
|
+
row_sep: :auto
|
226
227
|
}
|
227
228
|
begin
|
228
229
|
rows = CSV.parse(StringIO.new(data), **parser_opts)
|
@@ -235,7 +236,7 @@ module Reckon
|
|
235
236
|
index = data.index("\n", index) + 1 # skip over newline character
|
236
237
|
count += 1
|
237
238
|
end
|
238
|
-
rows = CSV.parse(StringIO.new(data[index
|
239
|
+
rows = CSV.parse(StringIO.new(data[index..]), **parser_opts)
|
239
240
|
rows[0..-footer_lines_to_skip]
|
240
241
|
end
|
241
242
|
end
|
data/lib/reckon/ledger_parser.rb
CHANGED
@@ -175,7 +175,7 @@ module Reckon
|
|
175
175
|
end
|
176
176
|
|
177
177
|
def format_row(row, line1, line2)
|
178
|
-
note = row[:note] ? "\t; row[:note]" : ""
|
178
|
+
note = row[:note] ? "\t; #{row[:note]}" : ""
|
179
179
|
out = "#{row[:pretty_date]}\t#{row[:description]}#{note}\n"
|
180
180
|
out += "\t#{line1.first}\t\t\t#{line1.last}\n"
|
181
181
|
out += "\t#{line2.first}\t\t\t#{line2.last}\n\n"
|
data/lib/reckon/logger.rb
CHANGED
data/lib/reckon/options.rb
CHANGED
@@ -4,7 +4,6 @@ module Reckon
|
|
4
4
|
# Singleton class for parsing command line flags
|
5
5
|
class Options
|
6
6
|
def self.parse_command_line_options(args = ARGV, stdin = $stdin)
|
7
|
-
cli = HighLine.new
|
8
7
|
options = { output_file: $stdout }
|
9
8
|
OptionParser.new do |opts|
|
10
9
|
opts.banner = "Usage: Reckon.rb [options]"
|
@@ -18,8 +17,17 @@ module Reckon
|
|
18
17
|
options[:bank_account] = a
|
19
18
|
end
|
20
19
|
|
21
|
-
|
22
|
-
|
20
|
+
options[:verbose] = Logger::WARN
|
21
|
+
opts.on("-v", "--v", "Run verbosely (show info log messages)") do
|
22
|
+
options[:verbose] = Logger::INFO
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("", "--verbose", "Run verbosely (show info log messages)") do
|
26
|
+
options[:verbose] = Logger::INFO
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("", "--vv", "Run very verbosely (show debug log messages)") do
|
30
|
+
options[:verbose] = Logger::DEBUG
|
23
31
|
end
|
24
32
|
|
25
33
|
opts.on("-i", "--inverse", "Use the negative of each amount") do |v|
|
@@ -58,6 +66,19 @@ module Reckon
|
|
58
66
|
options[:raw] = n
|
59
67
|
end
|
60
68
|
|
69
|
+
options[:sort] = :date
|
70
|
+
opts.on("", "--sort DATE|DESC|AMT", "Sort file by date, description, or amount") do |s|
|
71
|
+
if s == 'DESC'
|
72
|
+
options[:sort] = :description
|
73
|
+
elsif s == 'AMT'
|
74
|
+
options[:sort] = :money
|
75
|
+
elsif s == 'DATE'
|
76
|
+
options[:sort] = :date
|
77
|
+
else
|
78
|
+
raise "'#{s}' is not valid. valid sort options are DATE, DESC, AMT"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
61
82
|
opts.on("", "--date-column 3", Integer,
|
62
83
|
"Column number of the date column, starts from 1") do |col|
|
63
84
|
options[:date_column] = col
|
@@ -161,26 +182,35 @@ module Reckon
|
|
161
182
|
options[:string] = stdin.read
|
162
183
|
end
|
163
184
|
|
185
|
+
validate_options(options)
|
186
|
+
|
187
|
+
return options
|
188
|
+
end
|
189
|
+
|
190
|
+
def self.validate_options(options)
|
191
|
+
cli = HighLine.new
|
164
192
|
unless options[:file]
|
165
193
|
options[:file] = cli.ask("What CSV file should I parse? ")
|
166
|
-
|
167
|
-
puts "\
|
168
|
-
puts parser
|
194
|
+
if options[:file].empty?
|
195
|
+
puts "\nERROR: You must provide a CSV file to parse.\n"
|
169
196
|
exit
|
170
197
|
end
|
171
198
|
end
|
172
199
|
|
173
200
|
unless options[:bank_account]
|
174
|
-
|
201
|
+
if options[:unattended]
|
202
|
+
puts "ERROR: Must specify --account in unattended mode"
|
203
|
+
exit
|
204
|
+
end
|
175
205
|
|
176
|
-
options[:bank_account] = cli.ask("What is
|
206
|
+
options[:bank_account] = cli.ask("What is the Ledger account name?\n") do |q|
|
177
207
|
q.readline = true
|
178
208
|
q.validate = /^.{2,}$/
|
179
209
|
q.default = "Assets:Bank:Checking"
|
180
210
|
end
|
181
211
|
end
|
182
212
|
|
183
|
-
return
|
213
|
+
return true
|
184
214
|
end
|
185
215
|
end
|
186
216
|
end
|
data/lib/reckon/version.rb
CHANGED
@@ -8,7 +8,7 @@ ledger_file = ARGV[0]
|
|
8
8
|
account = ARGV[1]
|
9
9
|
seed = ARGV[2] ? ARGV[2].to_i : Random.new_seed
|
10
10
|
|
11
|
-
ledger = Reckon::LedgerParser.new(File.new(ledger_file))
|
11
|
+
ledger = Reckon::LedgerParser.new.parse(File.new(ledger_file))
|
12
12
|
matcher = Reckon::CosineSimilarity.new({})
|
13
13
|
|
14
14
|
train = []
|
@@ -50,3 +50,4 @@ end
|
|
50
50
|
# pp result.compact
|
51
51
|
puts "using #{seed} as random seed"
|
52
52
|
puts "true: #{result.count(nil)} false: #{result.count { |v| !v.nil? }}"
|
53
|
+
puts(result.filter { |v| !v.nil? })
|
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
|
-
Date | Amount | Description |
|
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 |
|
2
|
+
Date | Amount | Description |
|
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,20091224120000[0:GMT],"HOST 037196321563 MO 12/22SLICEHOST",-85.00
|
2
|
+
CHECK,20091224120000[0:GMT],"Book Store",-20.00
|
3
|
+
DEBIT,20091224120000[0:GMT],"GITHUB 041287430274 CA 12/22GITHUB 04",-7.00
|
4
|
+
CREDIT,20091223120000[0:GMT],"Some Company vendorpymt PPD ID: 59728JSL20",3520.00
|
5
|
+
CREDIT,20091223120000[0:GMT],"Blarg BLARG REVENUE PPD ID: 00jah78563",1558.52
|
6
|
+
DEBIT,20091221120000[0:GMT],"WEBSITE-BALANCE-17DEC09 12 12/17WEBSITE-BAL",-12.23
|
7
|
+
DEBIT,20091214120000[0:GMT],"WEBSITE-BALANCE-10DEC09 12 12/10WEBSITE-BAL",-20.96
|
8
|
+
CREDIT,20091211120000[0:GMT],"PAYPAL TRANSFER PPD ID: PAYPALSDSL",-116.22
|
9
|
+
CREDIT,20091210120000[0:GMT],"Some Company vendorpymt PPD ID: 5KL3832735",2105.00
|
@@ -0,0 +1,36 @@
|
|
1
|
+
2009-12-10 CREDIT; Some Company vendorpymt PPD ID: 5KL3832735
|
2
|
+
Assets:Bank:Checking $2,105.00
|
3
|
+
Income:Unknown
|
4
|
+
|
5
|
+
2009-12-11 CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL
|
6
|
+
Expenses:Unknown
|
7
|
+
Assets:Bank:Checking -$116.22
|
8
|
+
|
9
|
+
2009-12-14 DEBIT; WEBSITE-BALANCE-10DEC09 12 12/10WEBSITE-BAL
|
10
|
+
Expenses:Websites
|
11
|
+
Assets:Bank:Checking -$20.96
|
12
|
+
|
13
|
+
2009-12-21 DEBIT; WEBSITE-BALANCE-17DEC09 12 12/17WEBSITE-BAL
|
14
|
+
Expenses:Websites
|
15
|
+
Assets:Bank:Checking -$12.23
|
16
|
+
|
17
|
+
2009-12-23 CREDIT; Some Company vendorpymt PPD ID: 59728JSL20
|
18
|
+
Assets:Bank:Checking $3,520.00
|
19
|
+
Income:Unknown
|
20
|
+
|
21
|
+
2009-12-23 CREDIT; Blarg BLARG REVENUE PPD ID: 00jah78563
|
22
|
+
Assets:Bank:Checking $1,558.52
|
23
|
+
Income:Unknown
|
24
|
+
|
25
|
+
2009-12-24 DEBIT; GITHUB 041287430274 CA 12/22GITHUB 04
|
26
|
+
Expenses:Unknown
|
27
|
+
Assets:Bank:Checking -$7.00
|
28
|
+
|
29
|
+
2009-12-24 CHECK; Book Store
|
30
|
+
Expenses:Unknown
|
31
|
+
Assets:Bank:Checking -$20.00
|
32
|
+
|
33
|
+
2009-12-24 DEBIT; HOST 037196321563 MO 12/22SLICEHOST
|
34
|
+
Expenses:Unknown
|
35
|
+
Assets:Bank:Checking -$85.00
|
36
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
config:
|
2
|
+
similarity_threshold: 6
|
3
|
+
|
4
|
+
Income:
|
5
|
+
Salary:
|
6
|
+
- 'LÖN'
|
7
|
+
- 'Salary'
|
8
|
+
Expenses:
|
9
|
+
Bank:
|
10
|
+
- 'Comission'
|
11
|
+
- /mastercard/i
|
12
|
+
Rent:
|
13
|
+
- '0011223344' # Landlord bank number
|
14
|
+
Websites:
|
15
|
+
- /web/i
|
16
|
+
Books:
|
17
|
+
- 'Book'
|
18
|
+
'[Internal:Transfer]': # Virtual account
|
19
|
+
- '4433221100' # Your own account number
|
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.11.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:
|
13
|
+
date: 2025-03-04 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -274,6 +274,10 @@ files:
|
|
274
274
|
- spec/integration/two_money_columns_manual/input.csv
|
275
275
|
- spec/integration/two_money_columns_manual/output.ledger
|
276
276
|
- spec/integration/two_money_columns_manual/test_args
|
277
|
+
- spec/integration/unattended_config/input.csv
|
278
|
+
- spec/integration/unattended_config/output.ledger
|
279
|
+
- spec/integration/unattended_config/test_args
|
280
|
+
- spec/integration/unattended_config/tokens.yml
|
277
281
|
- spec/integration/yyyymmdd_date_example/input.csv
|
278
282
|
- spec/integration/yyyymmdd_date_example/output.ledger
|
279
283
|
- spec/integration/yyyymmdd_date_example/test_args
|