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.
@@ -20,23 +20,22 @@ describe Reckon::DateColumn do
20
20
  end
21
21
  describe "for" do
22
22
  it "should detect the date" do
23
- Reckon::DateColumn.new( ["13/12/2013"] ).for( 0 ).should ==
24
- Time.new( 2013, 12, 13, 12 )
25
- Reckon::DateColumn.new( ["01/14/2013"] ).for( 0 ).should ==
26
- Time.new( 2013, 01, 14, 12 )
27
- Reckon::DateColumn.new( ["13/12/2013", "21/11/2013"] ).for( 1 ).should ==
28
- Time.new( 2013, 11, 21, 12 )
29
- Reckon::DateColumn.new( ["2013-11-21"] ).for( 0 ).should ==
30
- Time.new( 2013, 11, 21, 12 )
23
+ expect(Reckon::DateColumn.new(%w[13/12/2013]).for(0))
24
+ .to eq(Date.new(2013, 12, 13))
25
+ expect(Reckon::DateColumn.new(%w[01/14/2013]).for(0))
26
+ .to eq(Date.new(2013, 1, 14))
27
+ expect(Reckon::DateColumn.new(%w[13/12/2013 21/11/2013]).for(1))
28
+ .to eq(Date.new(2013, 11, 21))
29
+ expect(Reckon::DateColumn.new( ["2013-11-21"] ).for( 0 ))
30
+ .to eq(Date.new(2013, 11, 21))
31
31
 
32
32
  end
33
33
 
34
34
  it "should correctly use endian_precedence" do
35
- Reckon::DateColumn.new( ["01/02/2013", "01/14/2013"] ).for(0).should ==
36
- Time.new( 2013, 01, 02, 12 )
37
- Reckon::DateColumn.new( ["01/02/2013", "14/01/2013"] ).for(0).should ==
38
- Time.new( 2013, 02, 01, 12 )
35
+ expect(Reckon::DateColumn.new(%w[01/02/2013 01/14/2013]).for(0))
36
+ .to eq(Date.new(2013, 1, 2))
37
+ expect(Reckon::DateColumn.new(%w[01/02/2013 14/01/2013]).for(0))
38
+ .to eq(Date.new(2013, 2, 1))
39
39
  end
40
40
  end
41
41
  end
42
-
@@ -20,14 +20,16 @@ describe Reckon::LedgerParser do
20
20
  formats = ["%Y/%m/%d", "%Y-%m-%d"]
21
21
  types = [' ! ', ' * ', ' ']
22
22
  delimiters = [" ", "\t", "\t\t"]
23
+ comment_chars = ';#%*|'
23
24
  currency_delimiters = delimiters + ['']
24
25
  currencies = ['', '$', '£']
25
26
  property_of do
26
27
  Rantly do
27
28
  description = Proc.new do
28
- sized(15){string}.tr(%q{'`:*\\},'').gsub(/\s+/, ' ').gsub(/^[!;<\[( ]+/, '')
29
+ sized(15){string}.tr(%q{'`:*\\},'').gsub(/\s+/, ' ').gsub(/^[!;<\[( #{comment_chars}]+/, '')
29
30
  end
30
31
  currency = choose(*currencies) # to be consistent within the transaction
32
+ single_line_comments = ";#|%*".split('').map { |n| "#{n} #{call(description)}" }
31
33
  comments = ['', '; ', "\t;#{call(description)}", " ; #{call(description)}"]
32
34
  date = Time.at(range(0, 1_581_389_644)).strftime(choose(*formats))
33
35
  codes = [' ', " (#{string(:alnum).tr('()', '')}) "]
@@ -48,23 +50,58 @@ describe Reckon::LedgerParser do
48
50
  ledger += "#{call(account_line)}\n"
49
51
  end
50
52
  ledger += "#{call(account)}\n"
53
+ ledger += choose(*single_line_comments) + "\n"
51
54
  ledger
52
55
  end
53
56
  end.check(1000) do |s|
54
57
  filter_format = lambda { |n| [n['date'], n['desc'], n['name'], sprintf("%.02f", n['amount'])] }
55
58
  headers = %w[date code desc name currency amount type commend]
56
59
  safe_s = Shellwords.escape(s)
57
- ledger_csv = `echo #{safe_s} | ledger csv --date-format '%Y-%m-%d' -f - `
58
- ledger_parser_csv = Reckon::LedgerParser.new(s, date_format: '%Y/%m/%d').to_csv.join("\n")
59
60
 
60
- expected = CSV.parse(ledger_csv.gsub('\"', '""'), headers: headers).map &filter_format
61
- actual = CSV.parse(ledger_parser_csv, headers: headers).map &filter_format
61
+ lp_csv = Reckon::LedgerParser.new(s, date_format: '%Y/%m/%d').to_csv.join("\n")
62
+ actual = CSV.parse(lp_csv, headers: headers).map(&filter_format)
63
+
64
+ ledger_csv = `echo #{safe_s} | ledger csv --date-format '%Y/%m/%d' -f - `
65
+ expected = CSV.parse(ledger_csv.gsub('\"', '""'), headers: headers).map(&filter_format)
62
66
  expected.length.times do |i|
63
67
  expect(actual[i]).to eq(expected[i])
64
68
  end
65
69
  end
66
70
  end
67
71
 
72
+ it 'should filter block comments' do
73
+ ledger = <<HERE
74
+ 1970/11/01 Dinner should show up
75
+ Assets:Checking -123.00
76
+ Expenses:Restaurants
77
+
78
+ comment
79
+
80
+ 1970/11/01 Lunch should NOT show up
81
+ Assets:Checking -12.00
82
+ Expenses:Restaurants
83
+
84
+ end comment
85
+ HERE
86
+ l = Reckon::LedgerParser.new(ledger)
87
+ expect(l.entries.length).to eq(1)
88
+ expect(l.entries.first[:desc]).to eq('Dinner should show up')
89
+
90
+ end
91
+
92
+ it 'should transaction comments' do
93
+ ledger = <<HERE
94
+ 2020-03-27 AMZN Mktp USX999H3203; Shopping; Sale
95
+ Expenses:Household $82.77
96
+ Liabilities:ChaseSapphire -$81.77
97
+ # END FINANCE SCRIPT OUTPUT Thu 02 Apr 2020 12:05:54 PM EDT
98
+ HERE
99
+ l = Reckon::LedgerParser.new(ledger)
100
+ expect(l.entries.first[:accounts].map { |n| n[:name] }).to eq(['Expenses:Household', 'Liabilities:ChaseSapphire'])
101
+ expect(l.entries.first[:accounts].size).to eq(2)
102
+ expect(l.entries.length).to eq(1)
103
+ end
104
+
68
105
  it "should ignore non-standard entries" do
69
106
  @ledger.entries.length.should == 7
70
107
  end
@@ -8,79 +8,92 @@ require 'reckon'
8
8
  describe Reckon::Money do
9
9
  describe "from_s" do
10
10
  it "should handle currency indicators" do
11
- Reckon::Money::from_s( "$2.00" ).should == 2.00
12
- Reckon::Money::from_s( "-$1025.67" ).should == -1025.67
13
- Reckon::Money::from_s( "$-1025.67" ).should == -1025.67
11
+ expect(Reckon::Money::from_s( "$2.00" )).to eq(2.00)
12
+ expect(Reckon::Money::from_s("-$1025.67")).to eq(-1025.67)
13
+ expect(Reckon::Money::from_s("$-1025.67")).to eq(-1025.67)
14
14
  end
15
15
 
16
16
  it "should handle the comma_separates_cents option correctly" do
17
- Reckon::Money::from_s( "$2,00", :comma_separates_cents => true ).should == 2.00
18
- Reckon::Money::from_s( "-$1025,67", :comma_separates_cents => true ).should == -1025.67
19
- Reckon::Money::from_s( "$-1025,67", :comma_separates_cents => true ).should == -1025.67
17
+ expect(Reckon::Money::from_s("$2,00", :comma_separates_cents => true)).to eq(2.00)
18
+ expect(Reckon::Money::from_s("-$1025,67", :comma_separates_cents => true )).to eq(-1025.67)
19
+ expect(Reckon::Money::from_s("$-1025,67", :comma_separates_cents => true )).to eq(-1025.67)
20
20
  end
21
21
 
22
22
  it "should return 0 for an empty string" do
23
- Reckon::Money::from_s( "" ).should == 0
23
+ expect(Reckon::Money::from_s("")).to eq(0)
24
24
  end
25
25
 
26
26
  it "should handle 1000 indicators correctly" do
27
- Reckon::Money::from_s( "$2.000,00", :comma_separates_cents => true ).should == 2000.00
28
- Reckon::Money::from_s( "-$1,025.67" ).should == -1025.67
27
+ expect(Reckon::Money::from_s("$2.000,00", :comma_separates_cents => true)).to eq(2000.00)
28
+ expect(Reckon::Money::from_s("-$1,025.67")).to eq(-1025.67)
29
29
  end
30
30
 
31
31
  it "should keep numbers together" do
32
- Reckon::Money::from_s( "1A1" ).should == 1
32
+ expect(Reckon::Money::from_s("1A1")).to eq(1)
33
33
  end
34
34
 
35
35
  it "should prefer numbers with precision of two" do
36
- Reckon::Money::from_s( "1A2.00" ).should == 2
37
- Reckon::Money::from_s( "2.00A1" ).should == 2
36
+ expect(Reckon::Money::from_s("1A2.00")).to eq(2)
37
+ expect(Reckon::Money::from_s("2.00A1")).to eq(2)
38
38
  end
39
39
 
40
40
  it "should handle arbitrary prefixes and postfixes" do
41
- Reckon::Money::from_s( "AB1.00C" ).should == 1
42
- Reckon::Money::from_s( "AB0C" ).should == 0
43
- Reckon::Money::from_s( "AB-2.00C" ).should == -2
41
+ expect(Reckon::Money::from_s("AB1.00C")).to eq(1)
42
+ expect(Reckon::Money::from_s("AB0C")).to eq(0)
43
+ expect(Reckon::Money::from_s("AB-2.00C")).to eq(-2)
44
44
  end
45
45
 
46
46
  it "should return nil if no numbers are found" do
47
- Reckon::Money::from_s( "BAC" ).should == nil
47
+ expect(Reckon::Money::from_s("BAC")).to be_nil()
48
48
  end
49
49
  end
50
50
 
51
51
  describe "pretty" do
52
52
  it "work with negative and positive numbers" do
53
- Reckon::Money.new( -20.00 ).pretty.should == "-$20.00"
54
- Reckon::Money.new( 1558.52 ).pretty.should == " $1558.52"
53
+ expect(Reckon::Money.new(-20.00).pretty).to eq("-$20.00")
54
+ expect(Reckon::Money.new(1558.52).pretty).to eq(" $1558.52")
55
55
  end
56
56
 
57
57
  it "work with other currencies such as €" do
58
- Reckon::Money.new( -20.00, :currency => "€", :suffixed => false ).pretty.should == "-€20.00"
59
- Reckon::Money.new( 1558.52, :currency => "€", :suffixed => false ).pretty.should == " €1558.52"
58
+ expect(Reckon::Money.new(-20.00, currency: "€", suffixed: false).pretty).to eq("-€20.00")
59
+ expect(Reckon::Money.new(1558.52, currency: "€", suffixed: false).pretty).to eq(" €1558.52")
60
60
  end
61
61
 
62
62
  it "work with suffixed currencies such as SEK" do
63
- Reckon::Money.new( -20.00, :currency => "SEK", :suffixed => true ).pretty.should == "-20.00 SEK"
64
- Reckon::Money.new( 1558.52, :currency => "SEK", :suffixed => true ).pretty.should == " 1558.52 SEK"
63
+ expect(Reckon::Money.new( -20.00, :currency => "SEK", :suffixed => true ).pretty).to eq("-20.00 SEK")
64
+ expect(Reckon::Money.new( 1558.52, :currency => "SEK", :suffixed => true ).pretty).to eq(" 1558.52 SEK")
65
65
  end
66
66
  end
67
67
 
68
68
  describe "likelihood" do
69
69
  it "should return the likelihood that a string represents money" do
70
- Reckon::Money::likelihood( "$20.00" ).should == 45
70
+ expect(Reckon::Money::likelihood( "$20.00" )).to eq(65)
71
+ end
72
+
73
+ it "should return neutral for empty string" do
74
+ expect(Reckon::Money::likelihood("")).to eq(0)
75
+ end
76
+
77
+ it "should recognize non-us currencies" do
78
+ expect(Reckon::Money::likelihood("£480.00")).to eq(30)
79
+ expect(Reckon::Money::likelihood("£1.480,00")).to eq(30)
80
+ end
81
+
82
+ it 'should not identify date columns as money' do
83
+ expect(Reckon::Money::likelihood("22.01.2014")).to eq(0)
71
84
  end
72
85
  end
73
86
 
74
87
  describe "equality" do
75
88
  it "should be comparable to other money" do
76
- Reckon::Money.new( 2.0 ).should == Reckon::Money.new( 2.0 )
77
- Reckon::Money.new( 1.0 ).should <= Reckon::Money.new( 2.0 )
78
- Reckon::Money.new( 3.0 ).should > Reckon::Money.new( 2.0 )
89
+ expect(Reckon::Money.new(2.0)).to eq(Reckon::Money.new(2.0))
90
+ expect(Reckon::Money.new(1.0)).to be <= Reckon::Money.new(2.0)
91
+ expect(Reckon::Money.new(3.0)).to be > Reckon::Money.new(2.0)
79
92
  end
80
93
  it "should be comparable to other float" do
81
- Reckon::Money.new( 2.0 ).should == 2.0
82
- Reckon::Money.new( 1.0 ).should <= 2.0
83
- Reckon::Money.new( 3.0 ).should > 2.0
94
+ expect(Reckon::Money.new(2.0)).to eq(2.0)
95
+ expect(Reckon::Money.new(1.0)).to be <= 2.0
96
+ expect(Reckon::Money.new(3.0)).to be > 2.0
84
97
  end
85
98
  end
86
99
  end
@@ -3,7 +3,26 @@ require 'rspec'
3
3
  require 'reckon'
4
4
 
5
5
  RSpec.configure do |config|
6
+ config.before(:all, &:silence_output)
7
+ config.after(:all, &:enable_output)
6
8
  def fixture_path(file)
7
9
  File.expand_path(File.join(File.dirname(__FILE__), "data_fixtures", file))
8
10
  end
9
11
  end
12
+
13
+ public
14
+
15
+ # Redirects stderr and stout to /dev/null.txt
16
+ def silence_output
17
+ # Store the original stderr and stdout in order to restore them later
18
+ @original_stdout = $stdout
19
+
20
+ # Redirect stderr and stdout
21
+ $stdout = File.new(File.join(File.dirname(__FILE__), 'test_log.txt'), 'w')
22
+ end
23
+
24
+ # Replace stderr and stdout so anything else is output correctly
25
+ def enable_output
26
+ $stdout = @original_stdout
27
+ @original_stdout = nil
28
+ end
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.5.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-02-19 00:00:00.000000000 Z
13
+ date: 2020-09-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -82,20 +82,6 @@ dependencies:
82
82
  - - ">="
83
83
  - !ruby/object:Gem::Version
84
84
  version: 1.5.2
85
- - !ruby/object:Gem::Dependency
86
- name: terminal-table
87
- requirement: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- version: 1.4.2
92
- type: :runtime
93
- prerelease: false
94
- version_requirements: !ruby/object:Gem::Requirement
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- version: 1.4.2
99
85
  - !ruby/object:Gem::Dependency
100
86
  name: rchardet
101
87
  requirement: !ruby/object:Gem::Requirement
@@ -135,12 +121,18 @@ files:
135
121
  - lib/reckon/app.rb
136
122
  - lib/reckon/cosine_similarity.rb
137
123
  - lib/reckon/csv_parser.rb
124
+ - lib/reckon/date_column.rb
138
125
  - lib/reckon/ledger_parser.rb
126
+ - lib/reckon/logger.rb
139
127
  - lib/reckon/money.rb
128
+ - lib/reckon/version.rb
140
129
  - reckon.gemspec
130
+ - spec/data_fixtures/51-sample.csv
131
+ - spec/data_fixtures/51-tokens.yml
141
132
  - spec/data_fixtures/73-sample.csv
142
133
  - spec/data_fixtures/73-tokens.yml
143
134
  - spec/data_fixtures/73-transactions.ledger
135
+ - spec/data_fixtures/85-date-example.csv
144
136
  - spec/data_fixtures/austrian_example.csv
145
137
  - spec/data_fixtures/bom_utf8_file.csv
146
138
  - spec/data_fixtures/broker_canada_example.csv
@@ -160,6 +152,7 @@ files:
160
152
  - spec/data_fixtures/some_other.csv
161
153
  - spec/data_fixtures/spanish_date_example.csv
162
154
  - spec/data_fixtures/suntrust.csv
155
+ - spec/data_fixtures/test_money_column.csv
163
156
  - spec/data_fixtures/tokens.yaml
164
157
  - spec/data_fixtures/two_money_columns.csv
165
158
  - spec/data_fixtures/yyyymmdd_date_example.csv
@@ -172,7 +165,8 @@ files:
172
165
  - spec/spec.opts
173
166
  - spec/spec_helper.rb
174
167
  homepage: https://github.com/cantino/reckon
175
- licenses: []
168
+ licenses:
169
+ - MIT
176
170
  metadata: {}
177
171
  post_install_message:
178
172
  rdoc_options: []
@@ -189,8 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
183
  - !ruby/object:Gem::Version
190
184
  version: '0'
191
185
  requirements: []
192
- rubyforge_project:
193
- rubygems_version: 2.7.6.2
186
+ rubygems_version: 3.1.2
194
187
  signing_key:
195
188
  specification_version: 4
196
189
  summary: Utility for interactively converting and labeling CSV files for the Ledger