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.
@@ -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.8"
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.}
@@ -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 => CHASE_CSV)
13
- @some_other_bank = Reckon::App.new(:string => SOME_OTHER_CSV)
14
- @two_money_columns = Reckon::App.new(:string => TWO_MONEY_COLUMNS_BANK)
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 "pretty_money_for" do
163
- it "work with negative and positive numbers" do
164
- @some_other_bank.pretty_money_for(1).should == "-$20.00"
165
- @some_other_bank.pretty_money_for(4).should == " $1558.52"
166
- @some_other_bank.pretty_money_for(7).should == "-$116.22"
167
- @some_other_bank.pretty_money_for(5).should == " $0.23"
168
- @some_other_bank.pretty_money_for(6).should == "-$0.96"
169
- end
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
- describe "merge_columns" do
191
- it "should work on adjacent columns" do
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