qiflib 0.0.2alpha → 0.0.4alpha

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.
data/README.md CHANGED
@@ -1 +1,12 @@
1
- README for qiflib
1
+ README for qiflib
2
+
3
+ file data/New_IMac_2009.qif
4
+ data/New_IMac_2009.qif: ISO-8859 English text, with CR line terminators
5
+
6
+ file data/ibank_20120328.qif
7
+ data/ibank_20120328.qif: ASCII English text
8
+
9
+ iconv -c -f ISO-8859 -t ASCII New_IMac_2009.qif > quicken_ascii.qif
10
+ iconv -c -f ISO-8859-15 -t ASCII New_IMac_2009.qif > quicken_ascii.qif
11
+ iconv -c -f ISO-8859-15 -t UTF-8 New_IMac_2009.qif > quicken_utf8.qif
12
+
data/lib/qiflib.rb CHANGED
@@ -1,12 +1,13 @@
1
1
 
2
2
  # standard libraries
3
- require 'csv'
3
+ require 'csv'
4
4
 
5
5
  # third-party libs
6
6
 
7
7
  # application code
8
+ require 'qiflib_constants'
9
+ require 'qiflib_category'
8
10
  require 'qiflib_date'
9
11
  require 'qiflib_money'
10
12
  require 'qiflib_transaction'
11
13
  require 'qiflib_util'
12
- require 'qiflib_version'
@@ -0,0 +1,34 @@
1
+
2
+ module Qiflib
3
+
4
+ class Category
5
+
6
+ attr_accessor :id
7
+ attr_accessor :name
8
+
9
+ def self.csv_header
10
+ CSV.generate do | csv |
11
+ csv << Qiflib::csv_category_field_names
12
+ end
13
+ end
14
+
15
+ def initialize(n)
16
+ @id, @name = 0, "#{n}".strip.downcase
17
+ end
18
+
19
+ def to_csv(idx=0)
20
+ CSV.generate do | csv |
21
+ csv << as_array(idx)
22
+ end
23
+ end
24
+
25
+ def as_array(idx=0)
26
+ array = []
27
+ array << idx + 1
28
+ array << name
29
+ array
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,44 @@
1
+ module Qiflib
2
+ VERSION = '0.0.4alpha'
3
+ DATE = '2012-04-07'
4
+ SOURCE_QUICKEN = 'quicken'
5
+ SOURCE_IBANK = 'ibank'
6
+
7
+ def self.csv_category_field_names
8
+ %w( id name )
9
+ end
10
+
11
+ def self.csv_transaction_field_names
12
+ %w(
13
+ id
14
+ acct_owner
15
+ acct_name
16
+ acct_type
17
+ date
18
+ amount
19
+ number
20
+ ibank_n
21
+ cleared
22
+ payee
23
+ category
24
+ memo
25
+ split1_amount
26
+ split1_category
27
+ split1_memo
28
+ split2_amount
29
+ split2_category
30
+ split2_memo
31
+ split3_amount
32
+ split3_category
33
+ split3_memo
34
+ address1
35
+ address2
36
+ address3
37
+ address4
38
+ address5
39
+ address6
40
+ eol_ind
41
+ )
42
+ end
43
+
44
+ end
data/lib/qiflib_money.rb CHANGED
@@ -20,7 +20,7 @@ module Qiflib
20
20
  end
21
21
 
22
22
  def cents
23
- string_value.tr(".","").to_f.to_i
23
+ string_value.tr("$.","").to_i
24
24
  end
25
25
 
26
26
  end
@@ -1,28 +1,62 @@
1
1
 
2
+ =begin
3
+
4
+ Quicken:
5
+ D3/10/09
6
+ PDuke Energy
7
+ M$61.01 due 3/23
8
+ T-62.00
9
+ A
10
+ A
11
+ A
12
+ A
13
+ A
14
+ A
15
+ N4548
16
+ L120 Electric
17
+ ^
18
+
19
+ iBank:
20
+ D3/10/09
21
+ PDuke Energy
22
+ M$61.01 due 3/23
23
+ T-62.
24
+ C4548
25
+ NCheck
26
+ L120 Electric
27
+ ^
28
+
29
+ =end
30
+
2
31
  module Qiflib
3
32
 
4
33
  class Transaction
5
34
 
6
- attr_reader :id # computed field
7
- attr_reader :acct_owner, :acct_name, :acct_type # constructor arg fields
8
- attr_reader :date, :amount, :cleared, :category, :number, :payee, :memo # data fields
9
- attr_reader :address
10
-
35
+ attr_accessor :id # computed field
36
+ attr_accessor :acct_owner, :acct_name, :acct_type, :source_app # constructor arg fields
37
+ attr_reader :date, :amount, :cleared, :category, :number, :payee, :memo # data fields
38
+ attr_reader :splits, :address, :ibank_n
11
39
 
12
- def initialize(acct_owner=nil, acct_name=nil, acct_type=nil)
40
+ def self.csv_header
41
+ CSV.generate do | csv |
42
+ csv << Qiflib::csv_transaction_field_names
43
+ end
44
+ end
45
+
46
+ def initialize(acct_owner=nil, acct_name=nil, acct_type=nil, source_app='quicken')
13
47
  if acct_owner
14
48
  @acct_owner = "#{acct_owner}".downcase
15
49
  @acct_name = "#{acct_name}".downcase
16
50
  @acct_type = "#{acct_type}".downcase
51
+ @source_app = "#{source_app}".downcase
17
52
  @id, @date, @amount, @cleared, @category, @number, @memo, @payee = 0, nil, nil, '', '', '', '', ''
18
- @splits, @curr_split, @address = [], {}, []
53
+ @splits, @curr_split, @address, @ibank_n = [], {}, [], ''
19
54
  end
20
55
  end
21
56
 
22
57
  def add_line(line)
23
58
  if line
24
59
  stripped = line.strip
25
- puts "Transaction.add_line: #{stripped}"
26
60
  if stripped.size > 0
27
61
  # Field Indicator Explanations:
28
62
  # D Date
@@ -44,17 +78,24 @@ module Qiflib
44
78
  elsif (stripped.match(/^P/))
45
79
  @payee = line_value(stripped)
46
80
  elsif (stripped.match(/^C/))
47
- @cleared = line_value(stripped)
81
+ if ibank?
82
+ @number = line_value(stripped)
83
+ else
84
+ @cleared = line_value(stripped)
85
+ end
48
86
  elsif (stripped.match(/^N/))
49
- @number = line_value(stripped)
87
+ if ibank?
88
+ @ibank_n = line_value(stripped)
89
+ else
90
+ @number = line_value(stripped)
91
+ end
50
92
  elsif (stripped.match(/^M/))
51
93
  @memo = line_value(stripped)
52
94
  elsif (stripped.match(/^L/))
53
- @category = line_value(stripped)
95
+ @category = line_value(stripped).downcase
54
96
  elsif (stripped.match(/^S/))
55
- current_split['category'] = line_value(stripped)
97
+ current_split['category'] = line_value(stripped).downcase
56
98
  elsif (stripped.match(/^E/))
57
- puts "E lv: #{line_value(stripped)}"
58
99
  current_split['memo'] = line_value(stripped)
59
100
  elsif (stripped.match(/^A/))
60
101
  @address << line_value(stripped)
@@ -67,8 +108,14 @@ module Qiflib
67
108
  end
68
109
  end
69
110
 
111
+ def ibank?
112
+ @source_app == 'ibank'
113
+ end
114
+
70
115
  def valid?
71
- return false if @date.nil?
116
+ return false if date.nil?
117
+ return false if date.to_s.size < 8
118
+ return false if date.to_s == '0000-00-00'
72
119
  true
73
120
  end
74
121
 
@@ -77,17 +124,48 @@ module Qiflib
77
124
  @curr_split
78
125
  end
79
126
 
80
- def splits
81
- @splits = [] if @splits.nil?
82
- @splits
83
- end
84
-
85
- def to_csv
127
+ def to_csv(idx=0)
86
128
  CSV.generate do | csv |
87
- csv << [ acct_owner, acct_name, acct_type, date, amount, cleared, category, number, payee, memo ]
129
+ csv << as_array(idx)
88
130
  end
89
131
  end
90
132
 
133
+ def as_array(idx=0)
134
+ array = []
135
+ array << idx + 1
136
+ array << acct_owner.downcase
137
+ array << acct_name.downcase
138
+ array << acct_type.downcase
139
+ array << date.to_s
140
+ array << amount.to_s
141
+ array << number
142
+ array << ibank_n
143
+ array << cleared
144
+ array << payee
145
+ array << category
146
+ array << memo
147
+ 3.times { | i |
148
+ if i < splits.size
149
+ array << splits[i]['amount']
150
+ array << splits[i]['category']
151
+ array << splits[i]['memo']
152
+ else
153
+ array << ''
154
+ array << ''
155
+ array << ''
156
+ end
157
+ }
158
+ 6.times { | i |
159
+ if i < address.size
160
+ array << address[i]
161
+ else
162
+ array << ''
163
+ end
164
+ }
165
+ array << 'x'
166
+ array
167
+ end
168
+
91
169
  def line_value(s)
92
170
  return '' if s.nil? || s.size < 1
93
171
  s[1, s.size].strip
data/lib/qiflib_util.rb CHANGED
@@ -3,40 +3,111 @@ module Qiflib
3
3
 
4
4
  class Util
5
5
 
6
- def self.qiftocsv(files=[])
6
+ def self.catetory_names(files_list)
7
+ categories, csv_lines = [], []
8
+ csv_lines << Qiflib::Category.csv_header
9
+ if files_list
10
+ files_list.each { | filename |
11
+ begin
12
+ file, in_cats = File.new(filename, 'r'), false
13
+ while (line = file.gets)
14
+ stripped = line.strip
15
+ if stripped.match(/^!Type:Cat/)
16
+ in_cats = true
17
+ else
18
+ if (stripped.match(/^!/)) && (stripped.size > 1)
19
+ in_cats = false
20
+ else
21
+ if in_cats
22
+ if (stripped.match(/^N/))
23
+ categories << line_value(stripped)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ file.close if file
30
+ rescue => err
31
+ file.close if file
32
+ puts "Exception: #{err.class.name} #{err.message} #{err.inspect}"
33
+ end
34
+ }
35
+ end
36
+ categories.uniq.sort.each_with_index { | name, idx |
37
+ cat = Qiflib::Category.new(name)
38
+ csv_lines << cat.to_csv(idx)
39
+ }
40
+ csv_lines
41
+ end
42
+
43
+ def self.transactions_to_csv(input_list)
7
44
  transactions, csv_lines = [], []
8
- if files
9
- files.each { | filename |
10
- process_qif_file(filename, transactions)
45
+ csv_lines << Qiflib::Transaction.csv_header
46
+ if input_list
47
+ input_list.each { | input_hash |
48
+ owner = input_hash[:owner]
49
+ filename = input_hash[:filename]
50
+ source = input_hash[:source]
51
+ process_file_for_transactions(owner, filename, source, transactions)
11
52
  }
12
- transactions.each { | tran |
13
- csv_lines << tran.to_csv
53
+ transactions.each_with_index { | tran, idx |
54
+ csv_lines << tran.to_csv(idx)
14
55
  }
15
56
  end
16
57
  csv_lines
17
58
  end
18
59
 
19
- def self.process_qif_file(filename, transactions)
60
+ def self.process_file_for_transactions(owner, filename, source, transactions)
20
61
  begin
21
62
  file = File.new(filename, 'r')
22
- current_tran = Qiflib::Transaction.new
63
+ in_acct_header, in_type_header, acct_name, acct_type = false, false, '?', '?'
64
+ current_tran = Qiflib::Transaction.new(owner, acct_name, acct_type, source)
65
+ line_number = 0
23
66
  while (line = file.gets)
67
+ line_number = line_number + 1
24
68
  stripped = line.strip
25
- if stripped == '^'
26
- if current_tran.valid?
27
- transactions << current_tran
28
- end
29
- current_tran = Qiflib::Transaction.new
69
+ if stripped.match(/^!Account/)
70
+ in_acct_header = true
71
+ elsif stripped.match(/^!Type/)
72
+ in_type_header = true
30
73
  else
31
- current_tran.add_line(stripped)
74
+ if in_acct_header
75
+ if stripped.match(/^N/)
76
+ acct_name = line_value(stripped)
77
+ current_tran.acct_name = acct_name
78
+ elsif stripped.match(/^T/)
79
+ acct_type = line_value(stripped)
80
+ current_tran.acct_type = acct_type
81
+ elsif stripped == '^'
82
+ in_acct_header = false
83
+ end
84
+ elsif in_type_header
85
+ if stripped == '^'
86
+ in_type_header = false
87
+ end
88
+ else
89
+ if stripped == '^'
90
+ if current_tran.valid?
91
+ transactions << current_tran
92
+ end
93
+ current_tran = Qiflib::Transaction.new(owner, acct_name, acct_type, source)
94
+ else
95
+ current_tran.add_line(stripped)
96
+ end
97
+ end
32
98
  end
33
99
  end
34
- file.close
100
+ file.close if file
35
101
  rescue => err
36
102
  puts "Exception: #{err.class.name} #{err.message} #{err.inspect}"
37
103
  end
38
104
  end
39
-
105
+
106
+ def self.line_value(s)
107
+ return '' if s.nil? || s.size < 1
108
+ s[1, s.size].strip
109
+ end
110
+
40
111
  end
41
112
 
42
113
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qiflib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2alpha
4
+ version: 0.0.4alpha
5
5
  prerelease: 5
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-03 00:00:00.000000000Z
12
+ date: 2012-04-07 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70134028206920 !ruby/object:Gem::Requirement
16
+ requirement: &70361534557220 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 2.9.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70134028206920
24
+ version_requirements: *70361534557220
25
25
  description: A ruby library for qif file processing.
26
26
  email: cjoakim@bellsouth.net
27
27
  executables: []
@@ -29,11 +29,12 @@ extensions: []
29
29
  extra_rdoc_files: []
30
30
  files:
31
31
  - lib/qiflib.rb
32
+ - lib/qiflib_category.rb
33
+ - lib/qiflib_constants.rb
32
34
  - lib/qiflib_date.rb
33
35
  - lib/qiflib_money.rb
34
36
  - lib/qiflib_transaction.rb
35
37
  - lib/qiflib_util.rb
36
- - lib/qiflib_version.rb
37
38
  - README.md
38
39
  homepage: http://rubygems.org/gems/qiflib
39
40
  licenses:
@@ -1,6 +0,0 @@
1
- module Qiflib
2
-
3
- VERSION = '0.0.2alpha'
4
- DATE = '2012-04-03'
5
-
6
- end