qiflib 0.0.2alpha → 0.0.4alpha

Sign up to get free protection for your applications and to get access to all the features.
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