reckon 0.3.8 → 0.3.9
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 +7 -0
- data/.ruby-version +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +31 -17
- data/bin/reckon +1 -1
- data/lib/reckon.rb +2 -0
- data/lib/reckon/app.rb +15 -219
- data/lib/reckon/csv_parser.rb +259 -0
- data/lib/reckon/money.rb +150 -0
- data/reckon.gemspec +2 -2
- data/spec/reckon/app_spec.rb +14 -270
- data/spec/reckon/csv_parser_spec.rb +393 -0
- data/spec/reckon/date_column_spec.rb +39 -0
- data/spec/reckon/money_column_spec.rb +52 -0
- data/spec/reckon/money_spec.rb +68 -0
- metadata +28 -35
data/lib/reckon/money.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
#coding: utf-8
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
module Reckon
|
5
|
+
class Money
|
6
|
+
include Comparable
|
7
|
+
attr_accessor :amount, :currency, :suffixed
|
8
|
+
def initialize( amount, options = {} )
|
9
|
+
if options[:inverse]
|
10
|
+
@amount = -1*amount.to_f
|
11
|
+
else
|
12
|
+
@amount = amount.to_f
|
13
|
+
end
|
14
|
+
@currency = options[:currency] || "$"
|
15
|
+
@suffixed = options[:suffixed]
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_f
|
19
|
+
return @amount
|
20
|
+
end
|
21
|
+
|
22
|
+
def -@
|
23
|
+
Money.new( -@amount, :currency => @currency, :suffixed => @suffixed )
|
24
|
+
end
|
25
|
+
|
26
|
+
def <=>( mon )
|
27
|
+
other_amount = mon.to_f
|
28
|
+
if @amount < other_amount
|
29
|
+
-1
|
30
|
+
elsif @amount > other_amount
|
31
|
+
1
|
32
|
+
else
|
33
|
+
0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def pretty( negate = false )
|
38
|
+
if @suffixed
|
39
|
+
(@amount >= 0 ? " " : "") + sprintf("%0.2f #{@currency}", @amount * (negate ? -1 : 1))
|
40
|
+
else
|
41
|
+
(@amount >= 0 ? " " : "") + sprintf("%0.2f", @amount * (negate ? -1 : 1)).gsub(/^((\-)|)(?=\d)/, "\\1#{@currency}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def Money::from_s( value, options = {} )
|
46
|
+
return nil if value.empty?
|
47
|
+
value = value.gsub(/\./, '').gsub(/,/, '.') if options[:comma_separates_cents]
|
48
|
+
amount = value.gsub(/[^\d\.]/, '').to_f
|
49
|
+
amount *= -1 if value =~ /[\(\-]/
|
50
|
+
Money.new( amount, options )
|
51
|
+
end
|
52
|
+
|
53
|
+
def Money::likelihood( entry )
|
54
|
+
money_score = 0
|
55
|
+
money_score += 20 if entry[/^[\-\+\(]{0,2}\$/]
|
56
|
+
money_score += 10 if entry[/^\$?\-?\$?\d+[\.,\d]*?[\.,]\d\d$/]
|
57
|
+
money_score += 10 if entry[/\d+[\.,\d]*?[\.,]\d\d$/]
|
58
|
+
money_score += entry.gsub(/[^\d\.\-\+,\(\)]/, '').length if entry.length < 7
|
59
|
+
money_score -= entry.length if entry.length > 8
|
60
|
+
money_score -= 20 if entry !~ /^[\$\+\.\-,\d\(\)]+$/
|
61
|
+
money_score
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class MoneyColumn < Array
|
66
|
+
def initialize( arr = [], options = {} )
|
67
|
+
arr.each { |str| self.push( Money.from_s( str, options ) ) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def positive?
|
71
|
+
self.each do |money|
|
72
|
+
return false if money < 0 if money
|
73
|
+
end
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def merge!( other_column )
|
78
|
+
invert = false
|
79
|
+
invert = true if self.positive? && other_column.positive?
|
80
|
+
self.each_with_index do |mon, i|
|
81
|
+
other = other_column[i]
|
82
|
+
if mon && !other
|
83
|
+
if invert
|
84
|
+
self[i]= -mon
|
85
|
+
end
|
86
|
+
elsif !mon && other
|
87
|
+
self[i] = other
|
88
|
+
else
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
self
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class DateColumn < Array
|
97
|
+
attr_accessor :endian_precedence
|
98
|
+
def initialize( arr = [], options = {} )
|
99
|
+
arr.each do |value|
|
100
|
+
if options[:date_format]
|
101
|
+
begin
|
102
|
+
value = Date.strptime(value, options[:date_format])
|
103
|
+
rescue
|
104
|
+
puts "I'm having trouble parsing #{value} with the desired format: #{options[:date_format]}"
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
else
|
108
|
+
value = [$1, $2, $3].join("/") if value =~ /^(\d{4})(\d{2})(\d{2})\d+\[\d+\:GMT\]$/ # chase format
|
109
|
+
value = [$3, $2, $1].join("/") if value =~ /^(\d{2})\.(\d{2})\.(\d{4})$/ # german format
|
110
|
+
value = [$3, $2, $1].join("/") if value =~ /^(\d{2})\-(\d{2})\-(\d{4})$/ # nordea format
|
111
|
+
value = [$1, $2, $3].join("/") if value =~ /^(\d{4})(\d{2})(\d{2})/ # yyyymmdd format
|
112
|
+
|
113
|
+
unless @endian_precedence # Try to detect endian_precedence
|
114
|
+
reg_match = value.match( /^(\d\d)\/(\d\d)\/\d\d\d?\d?/ )
|
115
|
+
# If first one is not \d\d/\d\d/\d\d\d?\d set it to default
|
116
|
+
if !reg_match
|
117
|
+
@endian_precedence = [:middle, :little]
|
118
|
+
elsif reg_match[1].to_i > 12
|
119
|
+
@endian_precedence = [:little]
|
120
|
+
elsif reg_match[2].to_i > 12
|
121
|
+
@endian_precedence = [:middle]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
self.push( value )
|
126
|
+
end
|
127
|
+
# if endian_precedence still nil, raise error
|
128
|
+
unless @endian_precedence || options[:date_format]
|
129
|
+
raise( "Unable to determine date format. Please specify using --date-format" )
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def for( index )
|
134
|
+
value = self.at( index )
|
135
|
+
guess = Chronic.parse(value, :context => :past,
|
136
|
+
:endian_precedence => @endian_precedence )
|
137
|
+
if guess.to_i < 953236800 && value =~ /\//
|
138
|
+
guess = Chronic.parse((value.split("/")[0...-1] + [(2000 + value.split("/").last.to_i).to_s]).join("/"), :context => :past,
|
139
|
+
:endian_precedence => @endian_precedence)
|
140
|
+
end
|
141
|
+
guess
|
142
|
+
end
|
143
|
+
|
144
|
+
def pretty_for(index)
|
145
|
+
self.for(index).strftime("%Y/%m/%d")
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
data/reckon.gemspec
CHANGED
@@ -3,8 +3,8 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = %q{reckon}
|
6
|
-
s.version = "0.3.
|
7
|
-
s.authors = ["Andrew Cantino"]
|
6
|
+
s.version = "0.3.9"
|
7
|
+
s.authors = ["Andrew Cantino", "BlackEdder"]
|
8
8
|
s.email = %q{andrew@iterationlabs.com}
|
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.}
|
data/spec/reckon/app_spec.rb
CHANGED
@@ -5,204 +5,26 @@ require "spec_helper"
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'reckon'
|
7
7
|
|
8
|
-
Reckon::App.settings[:testing] = true
|
9
|
-
|
10
8
|
describe Reckon::App do
|
11
9
|
before do
|
12
|
-
@chase = Reckon::App.new(:string =>
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@simple_csv = Reckon::App.new(:string => SIMPLE_CSV)
|
16
|
-
@german_date = Reckon::App.new(:string => GERMAN_DATE_EXAMPLE)
|
17
|
-
@danish_kroner_nordea = Reckon::App.new(:string => DANISH_KRONER_NORDEA_EXAMPLE, :csv_separator => ';', :comma_separates_cents => true)
|
18
|
-
@yyyymmdd_date = Reckon::App.new(:string => YYYYMMDD_DATE_EXAMPLE)
|
19
|
-
@spanish_date = Reckon::App.new(:string => SPANISH_DATE_EXAMPLE, :date_format => '%d/%m/%Y')
|
20
|
-
@english_date = Reckon::App.new(:string => ENGLISH_DATE_EXAMPLE)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should be in testing mode" do
|
24
|
-
@chase.settings[:testing].should be_true
|
25
|
-
Reckon::App.settings[:testing].should be_true
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "parse" do
|
29
|
-
it "should work with foreign character encodings" do
|
30
|
-
app = Reckon::App.new(:file => File.expand_path(File.join(File.dirname(__FILE__), "..", "data_fixtures", "extratofake.csv")))
|
31
|
-
app.columns[0][0..2].should == ["Data", "10/31/2012", "11/01/2012"]
|
32
|
-
app.columns[2].first.should == "Hist?rico"
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should work with other separators" do
|
36
|
-
Reckon::App.new(:string => "one;two\nthree;four", :csv_separator => ';').columns.should == [['one', 'three'], ['two', 'four']]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "columns" do
|
41
|
-
it "should return the csv transposed" do
|
42
|
-
@simple_csv.columns.should == [["entry1", "entry4"], ["entry2", "entry5"], ["entry3", "entry6"]]
|
43
|
-
@chase.columns.length.should == 4
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should be ok with empty lines" do
|
47
|
-
lambda {
|
48
|
-
Reckon::App.new(:string => "one,two\nthree,four\n\n\n\n\n").columns.should == [['one', 'three'], ['two', 'four']]
|
49
|
-
}.should_not raise_error
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "detect_columns" do
|
54
|
-
before do
|
55
|
-
@harder_date_example_csv = Reckon::App.new(:string => HARDER_DATE_EXAMPLE)
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should detect the money column" do
|
59
|
-
@chase.money_column_indices.should == [3]
|
60
|
-
@some_other_bank.money_column_indices.should == [3]
|
61
|
-
@two_money_columns.money_column_indices.should == [3, 4]
|
62
|
-
@harder_date_example_csv.money_column_indices.should == [1]
|
63
|
-
@danish_kroner_nordea.money_column_indices.should == [3]
|
64
|
-
@yyyymmdd_date.money_column_indices.should == [3]
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should detect the date column" do
|
68
|
-
@chase.date_column_index.should == 1
|
69
|
-
@some_other_bank.date_column_index.should == 1
|
70
|
-
@two_money_columns.date_column_index.should == 0
|
71
|
-
@harder_date_example_csv.date_column_index.should == 0
|
72
|
-
@danish_kroner_nordea.date_column_index.should == 0
|
73
|
-
@yyyymmdd_date.date_column_index.should == 1
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should consider all other columns to be description columns" do
|
77
|
-
@chase.description_column_indices.should == [0, 2]
|
78
|
-
@some_other_bank.description_column_indices.should == [0, 2]
|
79
|
-
@two_money_columns.description_column_indices.should == [1, 2, 5]
|
80
|
-
@harder_date_example_csv.description_column_indices.should == [2, 3, 4, 5, 6, 7]
|
81
|
-
@danish_kroner_nordea.description_column_indices.should == [1, 2, 4]
|
82
|
-
@yyyymmdd_date.description_column_indices.should == [0, 2]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
describe "each_index_backwards" do
|
87
|
-
it "should hit every index" do
|
88
|
-
count = 0
|
89
|
-
@chase.each_row_backwards { count += 1}
|
90
|
-
count.should == 9
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
describe "money_for" do
|
95
|
-
it "should return the appropriate fields" do
|
96
|
-
@chase.money_for(1).should == -20
|
97
|
-
@chase.money_for(4).should == 1558.52
|
98
|
-
@chase.money_for(7).should == -116.22
|
99
|
-
@some_other_bank.money_for(1).should == -20
|
100
|
-
@some_other_bank.money_for(4).should == 1558.52
|
101
|
-
@some_other_bank.money_for(7).should == -116.22
|
102
|
-
@two_money_columns.money_for(0).should == -76
|
103
|
-
@two_money_columns.money_for(1).should == 327.49
|
104
|
-
@two_money_columns.money_for(2).should == -800
|
105
|
-
@two_money_columns.money_for(3).should == -88.55
|
106
|
-
@two_money_columns.money_for(4).should == 88.55
|
107
|
-
@danish_kroner_nordea.money_for(0).should == -48.00
|
108
|
-
@danish_kroner_nordea.money_for(1).should == -79.00
|
109
|
-
@danish_kroner_nordea.money_for(2).should == 497.90
|
110
|
-
@danish_kroner_nordea.money_for(3).should == -995.00
|
111
|
-
@danish_kroner_nordea.money_for(4).should == -3452.90
|
112
|
-
@danish_kroner_nordea.money_for(5).should == -655.00
|
113
|
-
@yyyymmdd_date.money_for(0).should == -123.45
|
114
|
-
end
|
115
|
-
|
116
|
-
it "should handle the comma_separates_cents option correctly" do
|
117
|
-
european_csv = Reckon::App.new(:string => "$2,00;something\n1.025,67;something else", :csv_separator => ';', :comma_separates_cents => true)
|
118
|
-
european_csv.money_for(0).should == 2.00
|
119
|
-
european_csv.money_for(1).should == 1025.67
|
120
|
-
end
|
121
|
-
|
122
|
-
it "should return negated values if the inverse option is passed" do
|
123
|
-
inversed_csv = Reckon::App.new(:string => INVERSED_CREDIT_CARD, :inverse => true)
|
124
|
-
inversed_csv.money_for(0).should == -30.00
|
125
|
-
inversed_csv.money_for(3).should == 500.00
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe "date_for" do
|
130
|
-
it "should return a parsed date object" do
|
131
|
-
@chase.date_for(1).year.should == Time.parse("2009/12/24").year
|
132
|
-
@chase.date_for(1).month.should == Time.parse("2009/12/24").month
|
133
|
-
@chase.date_for(1).day.should == Time.parse("2009/12/24").day
|
134
|
-
@some_other_bank.date_for(1).year.should == Time.parse("2010/12/24").year
|
135
|
-
@some_other_bank.date_for(1).month.should == Time.parse("2010/12/24").month
|
136
|
-
@some_other_bank.date_for(1).day.should == Time.parse("2010/12/24").day
|
137
|
-
@german_date.date_for(1).year.should == Time.parse("2009/12/24").year
|
138
|
-
@german_date.date_for(1).month.should == Time.parse("2009/12/24").month
|
139
|
-
@german_date.date_for(1).day.should == Time.parse("2009/12/24").day
|
140
|
-
@danish_kroner_nordea.date_for(0).year.should == Time.parse("2012/11/16").year
|
141
|
-
@danish_kroner_nordea.date_for(0).month.should == Time.parse("2012/11/16").month
|
142
|
-
@danish_kroner_nordea.date_for(0).day.should == Time.parse("2012/11/16").day
|
143
|
-
@yyyymmdd_date.date_for(0).year.should == Time.parse("2012/12/31").year
|
144
|
-
@yyyymmdd_date.date_for(0).month.should == Time.parse("2012/12/31").month
|
145
|
-
@yyyymmdd_date.date_for(0).day.should == Time.parse("2012/12/31").day
|
146
|
-
@spanish_date.date_for(1).year.should == Time.parse("2009/12/02").year
|
147
|
-
@spanish_date.date_for(1).month.should == Time.parse("2009/12/02").month
|
148
|
-
@spanish_date.date_for(1).day.should == Time.parse("2009/12/02").day
|
149
|
-
@english_date.date_for(1).year.should == Time.parse("2009/12/24").year
|
150
|
-
@english_date.date_for(1).month.should == Time.parse("2009/12/24").month
|
151
|
-
@english_date.date_for(1).day.should == Time.parse("2009/12/24").day
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
describe "description_for" do
|
156
|
-
it "should return the combined fields that are not money for date fields" do
|
157
|
-
@chase.description_for(1).should == "CHECK; CHECK 2656"
|
158
|
-
@chase.description_for(7).should == "CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL"
|
159
|
-
end
|
10
|
+
@chase = Reckon::App.new(:string => BANK_CSV)
|
11
|
+
@rows = []
|
12
|
+
@chase.each_row_backwards { |row| @rows.push( row ) }
|
160
13
|
end
|
161
14
|
|
162
|
-
describe "
|
163
|
-
it "
|
164
|
-
@
|
165
|
-
@
|
166
|
-
@
|
167
|
-
@
|
168
|
-
@
|
169
|
-
|
170
|
-
|
171
|
-
it "work with other currencies such as €" do
|
172
|
-
euro_bank = Reckon::App.new(:string => SOME_OTHER_CSV, :currency => "€", :suffixed => false )
|
173
|
-
euro_bank.pretty_money_for(1).should == "-€20.00"
|
174
|
-
euro_bank.pretty_money_for(4).should == " €1558.52"
|
175
|
-
euro_bank.pretty_money_for(7).should == "-€116.22"
|
176
|
-
euro_bank.pretty_money_for(5).should == " €0.23"
|
177
|
-
euro_bank.pretty_money_for(6).should == "-€0.96"
|
178
|
-
end
|
179
|
-
|
180
|
-
it "work with suffixed currencies such as SEK" do
|
181
|
-
swedish_bank = Reckon::App.new(:string => SOME_OTHER_CSV, :currency => 'SEK', :suffixed => true )
|
182
|
-
swedish_bank.pretty_money_for(1).should == "-20.00 SEK"
|
183
|
-
swedish_bank.pretty_money_for(4).should == " 1558.52 SEK"
|
184
|
-
swedish_bank.pretty_money_for(7).should == "-116.22 SEK"
|
185
|
-
swedish_bank.pretty_money_for(5).should == " 0.23 SEK"
|
186
|
-
swedish_bank.pretty_money_for(6).should == "-0.96 SEK"
|
15
|
+
describe "each_row_backwards" do
|
16
|
+
it "should return rows with hashes" do
|
17
|
+
@rows[0][:pretty_date].should == "2009/12/10"
|
18
|
+
@rows[0][:pretty_money].should == " $2105.00"
|
19
|
+
@rows[0][:description].should == "CREDIT; Some Company vendorpymt PPD ID: 5KL3832735"
|
20
|
+
@rows[1][:pretty_date].should == "2009/12/11"
|
21
|
+
@rows[1][:pretty_money].should == "-$116.22"
|
22
|
+
@rows[1][:description].should == "CREDIT; PAYPAL TRANSFER PPD ID: PAYPALSDSL"
|
187
23
|
end
|
188
24
|
end
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
@simple_csv.merge_columns(0,1).should == [["entry1 entry2", "entry4 entry5"], ["entry3", "entry6"]]
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should work on non-adjacent columns" do
|
196
|
-
@simple_csv.merge_columns(0,2).should == [["entry1 entry3", "entry4 entry6"], ["entry2", "entry5"]]
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
|
201
|
-
# Data
|
202
|
-
|
203
|
-
SIMPLE_CSV = "entry1,entry2,entry3\nentry4,entry5,entry6"
|
204
|
-
|
205
|
-
CHASE_CSV = (<<-CSV).strip
|
25
|
+
|
26
|
+
#DATA
|
27
|
+
BANK_CSV = (<<-CSV).strip
|
206
28
|
DEBIT,20091224120000[0:GMT],"HOST 037196321563 MO 12/22SLICEHOST",-85.00
|
207
29
|
CHECK,20091224120000[0:GMT],"CHECK 2656",-20.00
|
208
30
|
DEBIT,20091224120000[0:GMT],"GITHUB 041287430274 CA 12/22GITHUB 04",-7.00
|
@@ -213,82 +35,4 @@ describe Reckon::App do
|
|
213
35
|
CREDIT,20091211120000[0:GMT],"PAYPAL TRANSFER PPD ID: PAYPALSDSL",-116.22
|
214
36
|
CREDIT,20091210120000[0:GMT],"Some Company vendorpymt PPD ID: 5KL3832735",2105.00
|
215
37
|
CSV
|
216
|
-
|
217
|
-
SOME_OTHER_CSV = (<<-CSV).strip
|
218
|
-
DEBIT,2011/12/24,"HOST 037196321563 MO 12/22SLICEHOST",($85.00)
|
219
|
-
CHECK,2010/12/24,"CHECK 2656",($20.00)
|
220
|
-
DEBIT,2009/12/24,"GITHUB 041287430274 CA 12/22GITHUB 04",($7.00)
|
221
|
-
CREDIT,2008/12/24,"Some Company vendorpymt PPD ID: 59728JSL20",$3520.00
|
222
|
-
CREDIT,2007/12/24,"Blarg BLARG REVENUE PPD ID: 00jah78563",$1558.52
|
223
|
-
DEBIT,2006/12/24,"WEBSITE-BALANCE-17DEC09 12 12/17WEBSITE-BAL",$.23
|
224
|
-
DEBIT,2005/12/24,"WEBSITE-BALANCE-10DEC09 12 12/10WEBSITE-BAL",($0.96)
|
225
|
-
CREDIT,2004/12/24,"PAYPAL TRANSFER PPD ID: PAYPALSDSL",($116.22)
|
226
|
-
CREDIT,2003/12/24,"Some Company vendorpymt PPD ID: 5KL3832735",$2105.00
|
227
|
-
CSV
|
228
|
-
|
229
|
-
INVERSED_CREDIT_CARD = (<<-CSV).strip
|
230
|
-
2013/01/17,2013/01/16,2013011702,DEBIT,2226,"VODAFONE PREPAY VISA M AUCKLAND NZL",30.00
|
231
|
-
2013/01/18,2013/01/17,2013011801,DEBIT,2226,"WILSON PARKING AUCKLAND NZL",4.60
|
232
|
-
2013/01/18,2013/01/17,2013011802,DEBIT,2226,"AUCKLAND TRANSPORT HENDERSON NZL",2.00
|
233
|
-
2013/01/19,2013/01/19,2013011901,CREDIT,2226,"INTERNET PAYMENT RECEIVED ",-500.00
|
234
|
-
2013/01/26,2013/01/23,2013012601,DEBIT,2226,"ITUNES NZ CORK IRL",64.99
|
235
|
-
2013/01/26,2013/01/25,2013012602,DEBIT,2226,"VODAFONE FXFLNE BBND R NEWTON NZL",90.26
|
236
|
-
2013/01/29,2013/01/29,2013012901,CREDIT,2101,"PAYMENT RECEIVED THANK YOU ",-27.75
|
237
|
-
2013/01/30,2013/01/29,2013013001,DEBIT,2226,"AUCKLAND TRANSPORT HENDERSON NZL",3.50
|
238
|
-
2013/02/05,2013/02/03,2013020501,DEBIT,2226,"Z BEACH RD AUCKLAND NZL",129.89
|
239
|
-
2013/02/05,2013/02/03,2013020502,DEBIT,2226,"TOURNAMENT KHYBER PASS AUCKLAND NZL",8.00
|
240
|
-
2013/02/05,2013/02/04,2013020503,DEBIT,2226,"VODAFONE PREPAY VISA M AUCKLAND NZL",30.00
|
241
|
-
2013/02/08,2013/02/07,2013020801,DEBIT,2226,"AKLD TRANSPORT PARKING AUCKLAND NZL",2.50
|
242
|
-
2013/02/08,2013/02/07,2013020802,DEBIT,2226,"AUCKLAND TRANSPORT HENDERSON NZL",3.50
|
243
|
-
2013/02/12,2013/02/11,2013021201,DEBIT,2226,"AKLD TRANSPORT PARKING AUCKLAND NZL",1.50
|
244
|
-
2013/02/17,2013/02/17,2013021701,CREDIT,2226,"INTERNET PAYMENT RECEIVED ",-12.00
|
245
|
-
2013/02/17,2013/02/17,2013021702,CREDIT,2226,"INTERNET PAYMENT RECEIVED ",-18.00
|
246
|
-
CSV
|
247
|
-
|
248
|
-
TWO_MONEY_COLUMNS_BANK = (<<-CSV).strip
|
249
|
-
4/1/2008,Check - 0000000122,122,-$76.00,"","$1,750.06"
|
250
|
-
3/28/2008,BLARG R SH 456930,"","",+$327.49,"$1,826.06"
|
251
|
-
3/27/2008,Check - 0000000112,112,-$800.00,"","$1,498.57"
|
252
|
-
3/26/2008,Check - 0000000251,251,-$88.55,"","$1,298.57"
|
253
|
-
3/26/2008,Check - 0000000251,251,"","+$88.55","$1,298.57"
|
254
|
-
CSV
|
255
|
-
|
256
|
-
HARDER_DATE_EXAMPLE = (<<-CSV).strip
|
257
|
-
10-Nov-9,-123.12,,,TRANSFER DEBIT INTERNET TRANSFER,INTERNET TRANSFER MORTGAGE,0.00,
|
258
|
-
09-Nov-10,123.12,,,SALARY SALARY,NGHSKS46383BGDJKD FOO BAR,432.12,
|
259
|
-
04-Nov-11,-1234.00,,,TRANSFER DEBIT INTERNET TRANSFER,INTERNET TRANSFER SAV TO MECU,0.00,
|
260
|
-
04-Nov-9,1234.00,,,TRANSFER CREDIT INTERNET TRANSFER,INTERNET TRANSFER,1234.00,
|
261
|
-
28-Oct-10,-123.12,,,TRANSFER DEBIT INTERNET TRANSFER,INTERNET TRANSFER SAV TO MORTGAGE,0.00,
|
262
|
-
CSV
|
263
|
-
GERMAN_DATE_EXAMPLE = (<<-CSV).strip
|
264
|
-
24.12.2009,Check - 0000000122,122,-$76.00,"","$1,750.06"
|
265
|
-
24.12.2009,BLARG R SH 456930,"","",+$327.49,"$1,826.06"
|
266
|
-
24.12.2009,Check - 0000000112,112,-$800.00,"","$1,498.57"
|
267
|
-
CSV
|
268
|
-
|
269
|
-
DANISH_KRONER_NORDEA_EXAMPLE = (<<-CSV).strip
|
270
|
-
16-11-2012;Dankort-nota DSB Kobenhavn 15149;16-11-2012;-48,00;26550,33
|
271
|
-
26-10-2012;Dankort-nota Ziggy Cafe 19471;26-10-2012;-79,00;26054,54
|
272
|
-
22-10-2012;Dankort-nota H&M Hennes & M 10681;23-10-2012;497,90;25433,54
|
273
|
-
12-10-2012;Visa kob DKK 995,00 WWW.ASOS.COM 00000 ;12-10-2012;-995,00;27939,54
|
274
|
-
12-09-2012;Dankort-nota B.J. TRADING E 14660;12-09-2012;-3452,90;26164,80
|
275
|
-
27-08-2012;Dankort-nota MATAS - 20319 18230;27-08-2012;-655,00;21127,45
|
276
|
-
CSV
|
277
|
-
|
278
|
-
YYYYMMDD_DATE_EXAMPLE = (<<-CSV).strip
|
279
|
-
DEBIT,20121231,"ODESK***BAL-27DEC12 650-12345 CA 12/28",-123.45
|
280
|
-
CSV
|
281
|
-
|
282
|
-
SPANISH_DATE_EXAMPLE = (<<-CSV).strip
|
283
|
-
02/12/2009,Check - 0000000122,122,-$76.00,"","$1,750.06"
|
284
|
-
02/12/2009,BLARG R SH 456930,"","",+$327.49,"$1,826.06"
|
285
|
-
02/12/2009,Check - 0000000112,112,-$800.00,"","$1,498.57"
|
286
|
-
CSV
|
287
|
-
|
288
|
-
ENGLISH_DATE_EXAMPLE = (<<-CSV).strip
|
289
|
-
24/12/2009,Check - 0000000122,122,-$76.00,"","$1,750.06"
|
290
|
-
24/12/2009,BLARG R SH 456930,"","",+$327.49,"$1,826.06"
|
291
|
-
24/12/2009,Check - 0000000112,112,-$800.00,"","$1,498.57"
|
292
|
-
CSV
|
293
|
-
|
294
38
|
end
|