reckon 0.5.0 → 0.6.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/.gitignore +3 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +55 -1
- data/Gemfile.lock +1 -5
- data/README.md +1 -1
- data/lib/reckon.rb +7 -9
- data/lib/reckon/app.rb +140 -69
- data/lib/reckon/cosine_similarity.rb +92 -89
- data/lib/reckon/csv_parser.rb +70 -113
- data/lib/reckon/date_column.rb +60 -0
- data/lib/reckon/ledger_parser.rb +11 -1
- data/lib/reckon/logger.rb +4 -0
- data/lib/reckon/money.rb +4 -59
- data/lib/reckon/version.rb +3 -0
- data/reckon.gemspec +3 -3
- data/spec/data_fixtures/51-sample.csv +8 -0
- data/spec/data_fixtures/51-tokens.yml +9 -0
- data/spec/data_fixtures/85-date-example.csv +2 -0
- data/spec/data_fixtures/test_money_column.csv +3 -0
- data/spec/reckon/app_spec.rb +32 -2
- data/spec/reckon/csv_parser_spec.rb +129 -129
- data/spec/reckon/date_column_spec.rb +12 -13
- data/spec/reckon/ledger_parser_spec.rb +42 -5
- data/spec/reckon/money_spec.rb +42 -29
- data/spec/spec_helper.rb +19 -0
- metadata +12 -19
data/lib/reckon/ledger_parser.rb
CHANGED
@@ -121,8 +121,14 @@ module Reckon
|
|
121
121
|
def parse(ledger)
|
122
122
|
@entries = []
|
123
123
|
new_entry = {}
|
124
|
+
in_comment = false
|
125
|
+
comment_chars = ';#%*|'
|
124
126
|
ledger.strip.split("\n").each do |entry|
|
125
|
-
|
127
|
+
# strip comment lines
|
128
|
+
in_comment = true if entry == 'comment'
|
129
|
+
in_comment = false if entry == 'end comment'
|
130
|
+
next if in_comment
|
131
|
+
next if entry =~ /^\s*[#{comment_chars}]/
|
126
132
|
|
127
133
|
# (date, type, code, description), type and code are optional
|
128
134
|
if (m = entry.match(%r{^(\d+[\d/-]+)\s+([*!])?\s*(\([^)]+\))?\s*(.*)$}))
|
@@ -134,7 +140,11 @@ module Reckon
|
|
134
140
|
desc: m[4].strip,
|
135
141
|
accounts: []
|
136
142
|
}
|
143
|
+
elsif entry =~ /^\s*$/ && new_entry[:date]
|
144
|
+
add_entry(new_entry)
|
145
|
+
new_entry = {}
|
137
146
|
elsif new_entry[:date] && entry =~ /^\s+/
|
147
|
+
LOGGER.info("Adding new account #{entry}")
|
138
148
|
new_entry[:accounts] << parse_account_line(entry)
|
139
149
|
else
|
140
150
|
LOGGER.info("Unknown entry type: #{entry}")
|
data/lib/reckon/money.rb
CHANGED
@@ -71,12 +71,13 @@ module Reckon
|
|
71
71
|
|
72
72
|
def Money::likelihood( entry )
|
73
73
|
money_score = 0
|
74
|
-
|
74
|
+
# digits separated by , or . with no more than 2 trailing digits
|
75
|
+
money_score += 40 if entry.match(/\d+[,.]\d{2}[^\d]*$/)
|
75
76
|
money_score += 10 if entry[/^\$?\-?\$?\d+[\.,\d]*?[\.,]\d\d$/]
|
76
77
|
money_score += 10 if entry[/\d+[\.,\d]*?[\.,]\d\d$/]
|
77
78
|
money_score += entry.gsub(/[^\d\.\-\+,\(\)]/, '').length if entry.length < 7
|
78
|
-
money_score -= entry.length if entry.length >
|
79
|
-
money_score -= 20 if entry !~ /^[\$\+\.\-,\d\(\)]+$/
|
79
|
+
money_score -= entry.length if entry.length > 12
|
80
|
+
money_score -= 20 if (entry !~ /^[\$\+\.\-,\d\(\)]+$/) && entry.length > 0
|
80
81
|
money_score
|
81
82
|
end
|
82
83
|
end
|
@@ -112,60 +113,4 @@ module Reckon
|
|
112
113
|
self
|
113
114
|
end
|
114
115
|
end
|
115
|
-
|
116
|
-
class DateColumn < Array
|
117
|
-
attr_accessor :endian_precedence
|
118
|
-
def initialize( arr = [], options = {} )
|
119
|
-
arr.each do |value|
|
120
|
-
if options[:date_format]
|
121
|
-
begin
|
122
|
-
value = Date.strptime(value, options[:date_format])
|
123
|
-
rescue
|
124
|
-
puts "I'm having trouble parsing #{value} with the desired format: #{options[:date_format]}"
|
125
|
-
exit 1
|
126
|
-
end
|
127
|
-
else
|
128
|
-
value = [$1, $2, $3].join("/") if value =~ /^(\d{4})(\d{2})(\d{2})\d+\[\d+\:GMT\]$/ # chase format
|
129
|
-
value = [$3, $2, $1].join("/") if value =~ /^(\d{2})\.(\d{2})\.(\d{4})$/ # german format
|
130
|
-
value = [$3, $2, $1].join("/") if value =~ /^(\d{2})\-(\d{2})\-(\d{4})$/ # nordea format
|
131
|
-
value = [$1, $2, $3].join("/") if value =~ /^(\d{4})\-(\d{2})\-(\d{2})$/ # yyyy-mm-dd format
|
132
|
-
value = [$1, $2, $3].join("/") if value =~ /^(\d{4})(\d{2})(\d{2})/ # yyyymmdd format
|
133
|
-
|
134
|
-
|
135
|
-
unless @endian_precedence # Try to detect endian_precedence
|
136
|
-
reg_match = value.match( /^(\d\d)\/(\d\d)\/\d\d\d?\d?/ )
|
137
|
-
# If first one is not \d\d/\d\d/\d\d\d?\d set it to default
|
138
|
-
if !reg_match
|
139
|
-
@endian_precedence = [:middle, :little]
|
140
|
-
elsif reg_match[1].to_i > 12
|
141
|
-
@endian_precedence = [:little]
|
142
|
-
elsif reg_match[2].to_i > 12
|
143
|
-
@endian_precedence = [:middle]
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
self.push( value )
|
148
|
-
end
|
149
|
-
# if endian_precedence still nil, raise error
|
150
|
-
unless @endian_precedence || options[:date_format]
|
151
|
-
raise( "Unable to determine date format. Please specify using --date-format" )
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def for( index )
|
156
|
-
value = self.at( index )
|
157
|
-
guess = Chronic.parse(value, :context => :past,
|
158
|
-
:endian_precedence => @endian_precedence )
|
159
|
-
if guess.to_i < 953236800 && value =~ /\//
|
160
|
-
guess = Chronic.parse((value.split("/")[0...-1] + [(2000 + value.split("/").last.to_i).to_s]).join("/"), :context => :past,
|
161
|
-
:endian_precedence => @endian_precedence)
|
162
|
-
end
|
163
|
-
guess
|
164
|
-
end
|
165
|
-
|
166
|
-
def pretty_for(index)
|
167
|
-
self.for(index).to_date.iso8601
|
168
|
-
end
|
169
|
-
|
170
|
-
end
|
171
116
|
end
|
data/reckon.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
$:.push File.expand_path("../lib", __FILE__)
|
2
|
-
|
2
|
+
require_relative 'lib/reckon/version'
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = %q{reckon}
|
@@ -9,10 +9,11 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.homepage = %q{https://github.com/cantino/reckon}
|
10
10
|
s.description = %q{Reckon automagically converts CSV files for use with the command-line accounting tool Ledger. It also helps you to select the correct accounts associated with the CSV data using Bayesian machine learning.}
|
11
11
|
s.summary = %q{Utility for interactively converting and labeling CSV files for the Ledger accounting tool.}
|
12
|
+
s.licenses = ['MIT']
|
12
13
|
|
13
14
|
s.files = `git ls-files`.split("\n")
|
14
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
-
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) }
|
16
17
|
s.require_paths = ["lib"]
|
17
18
|
|
18
19
|
s.add_development_dependency "rspec", ">= 1.2.9"
|
@@ -20,6 +21,5 @@ Gem::Specification.new do |s|
|
|
20
21
|
s.add_development_dependency "rantly", "= 1.2.0"
|
21
22
|
s.add_runtime_dependency "chronic", ">= 0.3.0"
|
22
23
|
s.add_runtime_dependency "highline", ">= 1.5.2"
|
23
|
-
s.add_runtime_dependency "terminal-table", ">= 1.4.2"
|
24
24
|
s.add_runtime_dependency "rchardet", ">= 1.8.0"
|
25
25
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
01/09/2015,05354 SUBWAY,8.19,,1000.00
|
2
|
+
02/18/2015,WENDY'S #6338,8.55,,1000.00
|
3
|
+
02/25/2015,WENDY'S #6338,8.55,,1000.00
|
4
|
+
02/25/2015,WENDY'S #6338,9.14,,1000.00
|
5
|
+
02/27/2015,WENDY'S #6338,5.85,,1000.00
|
6
|
+
03/09/2015,WENDY'S #6338,17.70,,1000.00
|
7
|
+
03/16/2015,WENDY'S #6338,11.15,,1000.00
|
8
|
+
03/23/2015,WENDY'S,10.12,,1000.00
|
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
|
@@ -107,6 +107,36 @@ describe Reckon::App do
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
+
context "Issue #64 - regression test" do
|
111
|
+
it 'should work for simple file' do
|
112
|
+
rows = []
|
113
|
+
app = Reckon::App.new(file: fixture_path('test_money_column.csv'))
|
114
|
+
expect { app.each_row_backwards { |n| rows << n } }
|
115
|
+
.to output(/Skipping row: 'Date, Note, Amount'/).to_stderr_from_any_process
|
116
|
+
expect(rows.length).to eq(2)
|
117
|
+
expect(rows[0][:pretty_date]).to eq('2012-03-22')
|
118
|
+
expect(rows[0][:pretty_money]).to eq(' $50.00')
|
119
|
+
expect(rows[1][:pretty_date]).to eq('2012-03-23')
|
120
|
+
expect(rows[1][:pretty_money]).to eq('-$10.00')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'Issue #51 - regression test' do
|
125
|
+
it 'should assign correct accounts with tokens' do
|
126
|
+
output = StringIO.new
|
127
|
+
Reckon::App.new(
|
128
|
+
file: fixture_path('51-sample.csv'),
|
129
|
+
unattended: true,
|
130
|
+
account_tokens_file: fixture_path('51-tokens.yml'),
|
131
|
+
ignore_columns: [5],
|
132
|
+
bank_account: 'Assets:Chequing',
|
133
|
+
output_file: output
|
134
|
+
).walk_backwards
|
135
|
+
expect(output.string).not_to include('Income:Unknown')
|
136
|
+
expect(output.string.scan('Expenses:Dining:Resturant').size).to eq(8)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
110
140
|
#DATA
|
111
141
|
BANK_CSV = (<<-CSV).strip
|
112
142
|
DEBIT,20091224120000[0:GMT],"HOST 037196321563 MO 12/22SLICEHOST",-85.00
|
@@ -5,38 +5,29 @@ require_relative "../spec_helper"
|
|
5
5
|
require 'rubygems'
|
6
6
|
require_relative '../../lib/reckon'
|
7
7
|
|
8
|
-
Reckon::CSVParser.settings[:testing] = true
|
9
|
-
|
10
8
|
describe Reckon::CSVParser do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@intuit_mint = Reckon::CSVParser.new(file: fixture_path('intuit_mint_example.csv'))
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should be in testing mode" do
|
31
|
-
@chase.settings[:testing].should be true
|
32
|
-
Reckon::CSVParser.settings[:testing].should be true
|
33
|
-
end
|
9
|
+
let(:chase) { Reckon::CSVParser.new(file: fixture_path('chase.csv')) }
|
10
|
+
let(:some_other_bank) { Reckon::CSVParser.new(file: fixture_path('some_other.csv')) }
|
11
|
+
let(:two_money_columns) { Reckon::CSVParser.new(file: fixture_path('two_money_columns.csv')) }
|
12
|
+
let(:suntrust_csv) { Reckon::CSVParser.new(file: fixture_path('suntrust.csv')) }
|
13
|
+
let(:simple_csv) { Reckon::CSVParser.new(file: fixture_path('simple.csv')) }
|
14
|
+
let(:nationwide) { Reckon::CSVParser.new(file: fixture_path('nationwide.csv'), csv_separator: ',', suffixed: true, currency: "POUND") }
|
15
|
+
let(:german_date) { Reckon::CSVParser.new(file: fixture_path('german_date_example.csv')) }
|
16
|
+
let(:danish_kroner_nordea) { Reckon::CSVParser.new(file: fixture_path('danish_kroner_nordea_example.csv'), csv_separator: ';', comma_separates_cents: true) }
|
17
|
+
let(:yyyymmdd_date) { Reckon::CSVParser.new(file: fixture_path('yyyymmdd_date_example.csv')) }
|
18
|
+
let(:spanish_date) { Reckon::CSVParser.new(file: fixture_path('spanish_date_example.csv'), date_format: '%d/%m/%Y') }
|
19
|
+
let(:english_date) { Reckon::CSVParser.new(file: fixture_path('english_date_example.csv')) }
|
20
|
+
let(:ing_csv) { Reckon::CSVParser.new(file: fixture_path('ing.csv'), comma_separates_cents: true ) }
|
21
|
+
let(:austrian_csv) { Reckon::CSVParser.new(file: fixture_path('austrian_example.csv'), comma_separates_cents: true, csv_separator: ';' ) }
|
22
|
+
let(:french_csv) { Reckon::CSVParser.new(file: fixture_path('french_example.csv'), csv_separator: ';', comma_separates_cents: true) }
|
23
|
+
let(:broker_canada) { Reckon::CSVParser.new(file: fixture_path('broker_canada_example.csv')) }
|
24
|
+
let(:intuit_mint) { Reckon::CSVParser.new(file: fixture_path('intuit_mint_example.csv')) }
|
34
25
|
|
35
26
|
describe "parse" do
|
36
27
|
it "should use binary encoding if none specified and chardet fails" do
|
37
28
|
allow(CharDet).to receive(:detect).and_return({'encoding' => nil})
|
38
29
|
app = Reckon::CSVParser.new(file: fixture_path("extratofake.csv"))
|
39
|
-
expect(app.try_encoding
|
30
|
+
expect(app.send(:try_encoding, "foobarbaz")).to eq("BINARY")
|
40
31
|
end
|
41
32
|
|
42
33
|
it "should work with foreign character encodings" do
|
@@ -76,8 +67,8 @@ describe Reckon::CSVParser do
|
|
76
67
|
|
77
68
|
describe "columns" do
|
78
69
|
it "should return the csv transposed" do
|
79
|
-
|
80
|
-
|
70
|
+
simple_csv.columns.should == [["entry1", "entry4"], ["entry2", "entry5"], ["entry3", "entry6"]]
|
71
|
+
chase.columns.length.should == 4
|
81
72
|
end
|
82
73
|
|
83
74
|
it "should be ok with empty lines" do
|
@@ -88,46 +79,44 @@ describe Reckon::CSVParser do
|
|
88
79
|
end
|
89
80
|
|
90
81
|
describe "detect_columns" do
|
91
|
-
|
92
|
-
@harder_date_example_csv = Reckon::CSVParser.new(file: fixture_path('harder_date_example.csv'))
|
93
|
-
end
|
82
|
+
let(:harder_date_example_csv) { Reckon::CSVParser.new(file: fixture_path('harder_date_example.csv')) }
|
94
83
|
|
95
84
|
it "should detect the money column" do
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
85
|
+
chase.money_column_indices.should == [3]
|
86
|
+
some_other_bank.money_column_indices.should == [3]
|
87
|
+
two_money_columns.money_column_indices.should == [3, 4]
|
88
|
+
suntrust_csv.money_column_indices.should == [3, 4]
|
89
|
+
nationwide.money_column_indices.should == [3, 4]
|
90
|
+
harder_date_example_csv.money_column_indices.should == [1]
|
91
|
+
danish_kroner_nordea.money_column_indices.should == [3]
|
92
|
+
yyyymmdd_date.money_column_indices.should == [3]
|
93
|
+
ing_csv.money_column_indices.should == [6]
|
94
|
+
austrian_csv.money_column_indices.should == [4]
|
95
|
+
french_csv.money_column_indices.should == [4]
|
96
|
+
broker_canada.money_column_indices.should == [8]
|
97
|
+
intuit_mint.money_column_indices.should == [3]
|
109
98
|
end
|
110
99
|
|
111
100
|
it "should detect the date column" do
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
101
|
+
chase.date_column_index.should == 1
|
102
|
+
some_other_bank.date_column_index.should == 1
|
103
|
+
two_money_columns.date_column_index.should == 0
|
104
|
+
harder_date_example_csv.date_column_index.should == 0
|
105
|
+
danish_kroner_nordea.date_column_index.should == 0
|
106
|
+
yyyymmdd_date.date_column_index.should == 1
|
107
|
+
french_csv.date_column_index.should == 1
|
108
|
+
broker_canada.date_column_index.should == 0
|
109
|
+
intuit_mint.date_column_index.should == 0
|
121
110
|
Reckon::CSVParser.new(:string => '2014-01-13,"22211100000",-10').date_column_index.should == 0
|
122
111
|
end
|
123
112
|
|
124
113
|
it "should consider all other columns to be description columns" do
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
114
|
+
chase.description_column_indices.should == [0, 2]
|
115
|
+
some_other_bank.description_column_indices.should == [0, 2]
|
116
|
+
two_money_columns.description_column_indices.should == [1, 2, 5]
|
117
|
+
harder_date_example_csv.description_column_indices.should == [2, 3, 4, 5, 6, 7]
|
118
|
+
danish_kroner_nordea.description_column_indices.should == [1, 2, 4]
|
119
|
+
yyyymmdd_date.description_column_indices.should == [0, 2]
|
131
120
|
end
|
132
121
|
end
|
133
122
|
|
@@ -143,36 +132,36 @@ describe Reckon::CSVParser do
|
|
143
132
|
|
144
133
|
describe "money_for" do
|
145
134
|
it "should return the appropriate fields" do
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
135
|
+
chase.money_for(1).should == -20
|
136
|
+
chase.money_for(4).should == 1558.52
|
137
|
+
chase.money_for(7).should == -116.22
|
138
|
+
some_other_bank.money_for(1).should == -20
|
139
|
+
some_other_bank.money_for(4).should == 1558.52
|
140
|
+
some_other_bank.money_for(7).should == -116.22
|
141
|
+
two_money_columns.money_for(0).should == -76
|
142
|
+
two_money_columns.money_for(1).should == 327.49
|
143
|
+
two_money_columns.money_for(2).should == -800
|
144
|
+
two_money_columns.money_for(3).should == -88.55
|
145
|
+
two_money_columns.money_for(4).should == 88.55
|
146
|
+
nationwide.money_for(0).should == 500.00
|
147
|
+
nationwide.money_for(1).should == -20.00
|
148
|
+
danish_kroner_nordea.money_for(0).should == -48.00
|
149
|
+
danish_kroner_nordea.money_for(1).should == -79.00
|
150
|
+
danish_kroner_nordea.money_for(2).should == 497.90
|
151
|
+
danish_kroner_nordea.money_for(3).should == -995.00
|
152
|
+
danish_kroner_nordea.money_for(4).should == -3452.90
|
153
|
+
danish_kroner_nordea.money_for(5).should == -655.00
|
154
|
+
yyyymmdd_date.money_for(0).should == -123.45
|
155
|
+
ing_csv.money_for(0).should == -136.13
|
156
|
+
ing_csv.money_for(1).should == 375.00
|
157
|
+
austrian_csv.money_for(0).should == -18.00
|
158
|
+
austrian_csv.money_for(2).should == 120.00
|
159
|
+
french_csv.money_for(0).should == -10.00
|
160
|
+
french_csv.money_for(1).should == -5.76
|
161
|
+
broker_canada.money_for(0).should == 12.55
|
162
|
+
broker_canada.money_for(1).should == -81.57
|
163
|
+
intuit_mint.money_for(0).should == 0.01
|
164
|
+
intuit_mint.money_for(1).should == -331.63
|
176
165
|
end
|
177
166
|
|
178
167
|
it "should handle the comma_separates_cents option correctly" do
|
@@ -200,59 +189,63 @@ describe Reckon::CSVParser do
|
|
200
189
|
|
201
190
|
describe "date_for" do
|
202
191
|
it "should return a parsed date object" do
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
192
|
+
chase.date_for(1).year.should == Time.parse("2009/12/24").year
|
193
|
+
chase.date_for(1).month.should == Time.parse("2009/12/24").month
|
194
|
+
chase.date_for(1).day.should == Time.parse("2009/12/24").day
|
195
|
+
some_other_bank.date_for(1).year.should == Time.parse("2010/12/24").year
|
196
|
+
some_other_bank.date_for(1).month.should == Time.parse("2010/12/24").month
|
197
|
+
some_other_bank.date_for(1).day.should == Time.parse("2010/12/24").day
|
198
|
+
german_date.date_for(1).year.should == Time.parse("2009/12/24").year
|
199
|
+
german_date.date_for(1).month.should == Time.parse("2009/12/24").month
|
200
|
+
german_date.date_for(1).day.should == Time.parse("2009/12/24").day
|
201
|
+
danish_kroner_nordea.date_for(0).year.should == Time.parse("2012/11/16").year
|
202
|
+
danish_kroner_nordea.date_for(0).month.should == Time.parse("2012/11/16").month
|
203
|
+
danish_kroner_nordea.date_for(0).day.should == Time.parse("2012/11/16").day
|
204
|
+
yyyymmdd_date.date_for(0).year.should == Time.parse("2012/12/31").year
|
205
|
+
yyyymmdd_date.date_for(0).month.should == Time.parse("2012/12/31").month
|
206
|
+
yyyymmdd_date.date_for(0).day.should == Time.parse("2012/12/31").day
|
207
|
+
spanish_date.date_for(1).year.should == Time.parse("2009/12/02").year
|
208
|
+
spanish_date.date_for(1).month.should == Time.parse("2009/12/02").month
|
209
|
+
spanish_date.date_for(1).day.should == Time.parse("2009/12/02").day
|
210
|
+
english_date.date_for(1).year.should == Time.parse("2009/12/24").year
|
211
|
+
english_date.date_for(1).month.should == Time.parse("2009/12/24").month
|
212
|
+
english_date.date_for(1).day.should == Time.parse("2009/12/24").day
|
213
|
+
nationwide.date_for(1).month.should == 10
|
214
|
+
ing_csv.date_for(1).month.should == Time.parse("2012/11/12").month
|
215
|
+
ing_csv.date_for(1).day.should == Time.parse("2012/11/12").day
|
216
|
+
broker_canada.date_for(5).year.should == 2014
|
217
|
+
broker_canada.date_for(5).month.should == 1
|
218
|
+
broker_canada.date_for(5).day.should == 7
|
219
|
+
intuit_mint.date_for(1).year.should == 2014
|
220
|
+
intuit_mint.date_for(1).month.should == 2
|
221
|
+
intuit_mint.date_for(1).day.should == 3
|
233
222
|
end
|
234
223
|
end
|
235
224
|
|
236
225
|
describe "description_for" do
|
237
226
|
it "should return the combined fields that are not money for date fields" do
|
238
|
-
|
239
|
-
|
227
|
+
chase.description_for(1).should == "CHECK; CHECK 2656"
|
228
|
+
chase.description_for(7).should == "CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL"
|
240
229
|
end
|
241
230
|
|
242
231
|
it "should not append empty description column" do
|
243
232
|
parser = Reckon::CSVParser.new(:string => '01/09/2015,05354 SUBWAY,8.19,,',:date_format => '%d/%m/%Y')
|
244
|
-
parser.description_column_indices.should == [1, 4]
|
245
233
|
parser.description_for(0).should == '05354 SUBWAY'
|
246
234
|
end
|
235
|
+
|
236
|
+
it "should handle nil description" do
|
237
|
+
parser = Reckon::CSVParser.new(string: '2015-09-01,test,3.99')
|
238
|
+
expect(parser.description_for(1)).to eq("")
|
239
|
+
end
|
247
240
|
end
|
248
241
|
|
249
242
|
describe "pretty_money_for" do
|
250
243
|
it "work with negative and positive numbers" do
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
244
|
+
some_other_bank.pretty_money_for(1).should == "-$20.00"
|
245
|
+
some_other_bank.pretty_money_for(4).should == " $1558.52"
|
246
|
+
some_other_bank.pretty_money_for(7).should == "-$116.22"
|
247
|
+
some_other_bank.pretty_money_for(5).should == " $0.23"
|
248
|
+
some_other_bank.pretty_money_for(6).should == "-$0.96"
|
256
249
|
end
|
257
250
|
|
258
251
|
it "work with other currencies such as €" do
|
@@ -274,8 +267,15 @@ describe Reckon::CSVParser do
|
|
274
267
|
end
|
275
268
|
|
276
269
|
it "should work with merge columns" do
|
277
|
-
|
278
|
-
|
270
|
+
nationwide.pretty_money_for(0).should == " 500.00 POUND"
|
271
|
+
nationwide.pretty_money_for(1).should == "-20.00 POUND"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe '85 regression test' do
|
276
|
+
it 'should detect correct date column' do
|
277
|
+
p = Reckon::CSVParser.new(file:fixture_path('85-date-example.csv'))
|
278
|
+
expect(p.date_column_index).to eq(2)
|
279
279
|
end
|
280
280
|
end
|
281
281
|
end
|