thefox-wallet 0.17.1 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,117 +2,117 @@
2
2
  require 'date'
3
3
 
4
4
  module TheFox::Wallet
5
-
6
- # Add a new Entry.
7
- class AddCommand < Command
8
-
9
- NAME = 'add'
10
-
11
- def run
12
- if @options[:entry_category].nil?
13
- @options[:entry_category] = 'default'
14
- end
15
-
16
- if @options[:is_interactively]
17
- # Interactive User Input
18
-
19
- print "title: [#{@options[:entry_title]}] "
20
- title_t = STDIN.gets.strip
21
- if title_t.length > 0
22
- # Search for '%d' in title.
23
- if @options[:entry_title] =~ /%d/
24
- # Like sprintf.
25
- @options[:entry_title] = @options[:entry_title] % title_t.split(',').map{ |s| s.strip }
26
- else
27
- @options[:entry_title] = title_t
28
- end
29
- end
30
-
31
- print "date: [#{@options[:entry_date]}] "
32
- date_t = STDIN.gets.strip
33
- if date_t.length > 0
34
- @options[:entry_date] = date_t
35
- end
36
-
37
- print "revenue: [#{@options[:entry_revenue]}] "
38
- revenue_t = revenue(STDIN.gets.strip)
39
- if !revenue_t.nil?
40
- @options[:entry_revenue] = revenue_t
41
- end
42
-
43
- print "expense: [#{@options[:entry_expense]}] "
44
- expense_t = expense(STDIN.gets.strip)
45
- if !expense_t.nil?
46
- @options[:entry_expense] = expense_t
47
- end
48
-
49
- print "category: [#{@options[:entry_category]}] "
50
- category_t = STDIN.gets.strip
51
- if category_t.length > 0
52
- @options[:entry_category] = category_t
53
- end
54
-
55
- print "comment: [#{@options[:entry_comment]}] "
56
- comment_t = STDIN.gets.strip
57
- if comment_t.length > 0
58
- @options[:entry_comment] = comment_t
59
- end
60
-
61
- puts '-' * 20
62
- end
63
-
64
- if @options[:entry_title].nil?
65
- raise "Option --title is required for command '#{NAME}'"
66
- end
67
-
68
- # --force option
69
- # --id option
70
- is_unique = !@options[:force] && @options[:entry_id]
71
-
72
- puts "id: '#{@options[:entry_id]}'"
73
- puts "title: '#{@options[:entry_title]}'"
74
- puts "date: " << Date.parse(@options[:entry_date]).to_s
75
- puts "revenue: " << NUMBER_FORMAT % @options[:entry_revenue]
76
- puts "expense: " << NUMBER_FORMAT % @options[:entry_expense]
77
- puts "balance: " << NUMBER_FORMAT % [@options[:entry_revenue] + @options[:entry_expense]]
78
- puts "category: #{@options[:entry_category]}"
79
- puts "comment: '#{@options[:entry_comment]}'"
80
- puts "force: #{@options[:force] ? 'YES' : 'NO'}"
81
- puts "unique: #{is_unique ? 'YES' : 'NO'} (#{is_unique})"
82
-
83
- # Create new Entry.
84
- entry = Entry.new(@options[:entry_id], @options[:entry_title], @options[:entry_date], @options[:entry_revenue], @options[:entry_expense], @options[:entry_category], @options[:entry_comment])
85
-
86
- # Initialize Wallet.
87
- wallet = Wallet.new(@options[:wallet_path])
88
-
89
- # Add Entry to Wallet.
90
- added = wallet.add(entry, is_unique)
91
-
92
- puts "added: #{added ? 'YES' : 'NO'}"
93
-
94
- added
95
- end
96
-
97
- # @TODO replace with Wumber.
98
- def revenue(revenue_s)
99
- if !revenue_s.nil? && revenue_s.length > 0
100
- # Replace , with . in numbers. '1,23' means '1.23'.
101
- # eval the revenue so calculations are solved.
102
- eval(revenue_s.to_s.gsub(/,/, '.')).to_f.round(NUMBER_ROUND).abs
103
- end
104
- end
105
-
106
- # @TODO replace with Wumber.
107
- def expense(expense_s)
108
- if !expense_s.nil? && expense_s.length > 0
109
- # Replace , with . in numbers. '1,23' means '1.23'.
110
- # eval the revenue so calculations are solved.
111
- # Expenses are always minus.
112
- -eval(expense_s.to_s.gsub(/,/, '.')).to_f.round(NUMBER_ROUND).abs
113
- end
114
- end
115
-
116
- end
117
-
5
+
6
+ # Add a new Entry.
7
+ class AddCommand < Command
8
+
9
+ NAME = 'add'
10
+
11
+ def run
12
+ if @options[:entry_category].nil?
13
+ @options[:entry_category] = 'default'
14
+ end
15
+
16
+ if @options[:is_interactively]
17
+ # Interactive User Input
18
+
19
+ print "title: [#{@options[:entry_title]}] "
20
+ title_t = STDIN.gets.strip
21
+ if title_t.length > 0
22
+ # Search for '%d' in title.
23
+ if @options[:entry_title] =~ /%d/
24
+ # Like sprintf.
25
+ @options[:entry_title] = @options[:entry_title] % title_t.split(',').map{ |s| s.strip }
26
+ else
27
+ @options[:entry_title] = title_t
28
+ end
29
+ end
30
+
31
+ print "date: [#{@options[:entry_date]}] "
32
+ date_t = STDIN.gets.strip
33
+ if date_t.length > 0
34
+ @options[:entry_date] = date_t
35
+ end
36
+
37
+ print "revenue: [#{@options[:entry_revenue]}] "
38
+ revenue_t = revenue(STDIN.gets.strip)
39
+ if !revenue_t.nil?
40
+ @options[:entry_revenue] = revenue_t
41
+ end
42
+
43
+ print "expense: [#{@options[:entry_expense]}] "
44
+ expense_t = expense(STDIN.gets.strip)
45
+ if !expense_t.nil?
46
+ @options[:entry_expense] = expense_t
47
+ end
48
+
49
+ print "category: [#{@options[:entry_category]}] "
50
+ category_t = STDIN.gets.strip
51
+ if category_t.length > 0
52
+ @options[:entry_category] = category_t
53
+ end
54
+
55
+ print "comment: [#{@options[:entry_comment]}] "
56
+ comment_t = STDIN.gets.strip
57
+ if comment_t.length > 0
58
+ @options[:entry_comment] = comment_t
59
+ end
60
+
61
+ puts '-' * 20
62
+ end
63
+
64
+ if @options[:entry_title].nil?
65
+ raise "Option --title is required for command '#{NAME}'"
66
+ end
67
+
68
+ # --force option
69
+ # --id option
70
+ is_unique = !@options[:force] && @options[:entry_id]
71
+
72
+ puts "id: '#{@options[:entry_id]}'"
73
+ puts "title: '#{@options[:entry_title]}'"
74
+ puts "date: " << Date.parse(@options[:entry_date]).to_s
75
+ puts "revenue: " << NUMBER_FORMAT % @options[:entry_revenue]
76
+ puts "expense: " << NUMBER_FORMAT % @options[:entry_expense]
77
+ puts "balance: " << NUMBER_FORMAT % [@options[:entry_revenue] + @options[:entry_expense]]
78
+ puts "category: #{@options[:entry_category]}"
79
+ puts "comment: '#{@options[:entry_comment]}'"
80
+ puts "force: #{@options[:force] ? 'YES' : 'NO'}"
81
+ puts "unique: #{is_unique ? 'YES' : 'NO'} (#{is_unique})"
82
+
83
+ # Create new Entry.
84
+ entry = Entry.new(@options[:entry_id], @options[:entry_title], @options[:entry_date], @options[:entry_revenue], @options[:entry_expense], @options[:entry_category], @options[:entry_comment])
85
+
86
+ # Initialize Wallet.
87
+ wallet = Wallet.new(@options[:wallet_path])
88
+
89
+ # Add Entry to Wallet.
90
+ added = wallet.add(entry, is_unique)
91
+
92
+ puts "added: #{added ? 'YES' : 'NO'}"
93
+
94
+ added
95
+ end
96
+
97
+ # @TODO replace with Wumber.
98
+ def revenue(revenue_s)
99
+ if !revenue_s.nil? && revenue_s.length > 0
100
+ # Replace , with . in numbers. '1,23' means '1.23'.
101
+ # eval the revenue so calculations are solved.
102
+ eval(revenue_s.to_s.gsub(/,/, '.')).to_f.round(NUMBER_ROUND).abs
103
+ end
104
+ end
105
+
106
+ # @TODO replace with Wumber.
107
+ def expense(expense_s)
108
+ if !expense_s.nil? && expense_s.length > 0
109
+ # Replace , with . in numbers. '1,23' means '1.23'.
110
+ # eval the revenue so calculations are solved.
111
+ # Expenses are always minus.
112
+ -eval(expense_s.to_s.gsub(/,/, '.')).to_f.round(NUMBER_ROUND).abs
113
+ end
114
+ end
115
+
116
+ end
117
+
118
118
  end
@@ -1,16 +1,16 @@
1
1
 
2
2
  module TheFox::Wallet
3
-
4
- # List all used categories.
5
- class CategoriesCommand < Command
6
-
7
- NAME = 'categories'
8
-
9
- def run
10
- wallet = Wallet.new(@options[:wallet_path])
11
- puts wallet.categories
12
- end
13
-
14
- end
15
-
3
+
4
+ # List all used categories.
5
+ class CategoriesCommand < Command
6
+
7
+ NAME = 'categories'
8
+
9
+ def run
10
+ wallet = Wallet.new(@options[:wallet_path])
11
+ puts wallet.categories
12
+ end
13
+
14
+ end
15
+
16
16
  end
@@ -2,17 +2,17 @@
2
2
  require 'pathname'
3
3
 
4
4
  module TheFox::Wallet
5
-
6
- # Clear temp and cache files.
7
- class ClearCommand < Command
8
-
9
- NAME = 'clear'
10
-
11
- def run
12
- wallet = Wallet.new(@options[:wallet_path])
13
- wallet.logger = @options[:logger]
14
- wallet.clear
15
- end
16
-
17
- end
5
+
6
+ # Clear temp and cache files.
7
+ class ClearCommand < Command
8
+
9
+ NAME = 'clear'
10
+
11
+ def run
12
+ wallet = Wallet.new(@options[:wallet_path])
13
+ wallet.logger = @options[:logger]
14
+ wallet.clear
15
+ end
16
+
17
+ end
18
18
  end
@@ -1,33 +1,33 @@
1
1
 
2
2
  module TheFox::Wallet
3
-
4
- # Import or export to/from CSV file format.
5
- class CsvCommand < Command
6
-
7
- NAME = 'csv'
8
-
9
- def run
10
- if @options[:path].nil?
11
- raise "Option --path is required for command '#{NAME}'"
12
- end
13
-
14
- wallet = Wallet.new(@options[:wallet_path])
15
- wallet.logger = @options[:logger]
16
-
17
- # Import by default.
18
- if @options[:is_import] || !@options[:is_export]
19
- # Import
20
- @options[:logger].info("import csv #{@options[:path]} ...") if @options[:logger]
21
- wallet.import_csv_file(@options[:path])
22
- @options[:logger].info("import csv #{@options[:path]} done") if @options[:logger]
23
- elsif @options[:is_export]
24
- # Export
25
- @options[:logger].info("export csv #{@options[:path]} ...") if @options[:logger]
26
- wallet.export_csv_file(@options[:path])
27
- @options[:logger].info("export csv #{@options[:path]} done") if @options[:logger]
28
- end
29
- end
30
-
31
- end
32
-
3
+
4
+ # Import or export to/from CSV file format.
5
+ class CsvCommand < Command
6
+
7
+ NAME = 'csv'
8
+
9
+ def run
10
+ if @options[:path].nil?
11
+ raise "Option --path is required for command '#{NAME}'"
12
+ end
13
+
14
+ wallet = Wallet.new(@options[:wallet_path])
15
+ wallet.logger = @options[:logger]
16
+
17
+ # Import by default.
18
+ if @options[:is_import] || !@options[:is_export]
19
+ # Import
20
+ @options[:logger].info("import csv #{@options[:path]} ...") if @options[:logger]
21
+ wallet.import_csv_file(@options[:path])
22
+ @options[:logger].info("import csv #{@options[:path]} done") if @options[:logger]
23
+ elsif @options[:is_export]
24
+ # Export
25
+ @options[:logger].info("export csv #{@options[:path]} ...") if @options[:logger]
26
+ wallet.export_csv_file(@options[:path])
27
+ @options[:logger].info("export csv #{@options[:path]} done") if @options[:logger]
28
+ end
29
+ end
30
+
31
+ end
32
+
33
33
  end
@@ -2,24 +2,24 @@
2
2
  require 'pathname'
3
3
 
4
4
  module TheFox::Wallet
5
-
6
- # Exports a wallet as HTML.
7
- # List all years in an index HTML file and all months for each year.
8
- # Generates a HTML file for each month based on entries.
9
- class HtmlCommand < Command
10
-
11
- NAME = 'html'
12
-
13
- def run
14
- if @options[:path]
15
- html_path = Pathname.new(@options[:path]).expand_path
16
- end
17
-
18
- wallet = Wallet.new(@options[:wallet_path])
19
- wallet.logger = @options[:logger]
20
- wallet.generate_html(html_path, @options[:entry_date_start], @options[:entry_date_end], @options[:entry_category])
21
- end
22
-
23
- end
24
-
5
+
6
+ # Exports a wallet as HTML.
7
+ # List all years in an index HTML file and all months for each year.
8
+ # Generates a HTML file for each month based on entries.
9
+ class HtmlCommand < Command
10
+
11
+ NAME = 'html'
12
+
13
+ def run
14
+ if @options[:path]
15
+ html_path = Pathname.new(@options[:path]).expand_path
16
+ end
17
+
18
+ wallet = Wallet.new(@options[:wallet_path])
19
+ wallet.logger = @options[:logger]
20
+ wallet.generate_html(html_path, @options[:entry_date_start], @options[:entry_date_end], @options[:entry_category])
21
+ end
22
+
23
+ end
24
+
25
25
  end
@@ -1,176 +1,171 @@
1
1
 
2
2
  module TheFox::Wallet
3
-
4
- # List entries. Per default this command lists all entries of today.
5
- # @TODO Use terminal-table for output? https://github.com/tj/terminal-table
6
- class ListCommand < Command
7
-
8
- NAME = 'list'
9
-
10
- def run
11
- puts
12
-
13
- wallet = Wallet.new(@options[:wallet_path])
14
- entries = wallet.entries(@options[:entry_date], @options[:entry_category].to_s)
15
-
16
- # Get max length of all columns.
17
- entries_l = entries
18
- .map{ |day_name, day_items| day_items.count }
19
- .inject{ |sum, n| sum + n }
20
- .to_s
21
- .length
22
- title_l = entries
23
- .map{ |month_item| month_item[1].map{ |day_item| day_item['title'].length }}
24
- .flatten
25
- .max
26
- .to_i
27
- revenue_l = entries
28
- .map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['revenue']).length } }
29
- .flatten
30
- .max
31
- .to_i
32
- expense_l = entries
33
- .map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['expense']).length } }
34
- .flatten
35
- .max
36
- .to_i
37
- balance_l = entries
38
- .map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['balance']).length } }
39
- .flatten
40
- .max
41
- .to_i
42
- category_l = entries
43
- .map{ |month_item| month_item[1].map{ |day_item| day_item['category'].length } }
44
- .flatten
45
- .max
46
- .to_i
47
- comment_l = entries
48
- .map{ |month_item| month_item[1].map{ |day_item| day_item['comment'].length } }
49
- .flatten
50
- .max
51
- .to_i
52
-
53
- has_category_col = entries.map{ |month_item| month_item[1].map{ |day_item| day_item['category'] } }.flatten.select{ |i| i != 'default' }.count > 0
54
- has_comment_col = entries
55
- .map{ |month_item| month_item[1].map{ |day_item| day_item['comment'] } }
56
- .flatten
57
- .select{ |i| i != '' }
58
- .count > 0
59
-
60
- # Limit some columns to a maximum length.
61
- if title_l < 6
62
- title_l = 6
63
- end
64
- if title_l > 25
65
- title_l = 25
66
- end
67
-
68
- if revenue_l < 7
69
- revenue_l = 7
70
- end
71
- if expense_l < 7
72
- expense_l = 7
73
- end
74
- if balance_l < 7
75
- balance_l = 7
76
- end
77
- if category_l < 8
78
- category_l = 8
79
- end
80
- if comment_l > 25
81
- comment_l = 25
82
- end
83
-
84
- # Format String for each column.
85
- entries_f = "%#{entries_l}s"
86
- title_f = "%-#{title_l}s"
87
- revenue_f = "%#{revenue_l}s"
88
- expense_f = "%#{expense_l}s"
89
- balance_f = "%#{balance_l}s"
90
- category_f = "%-#{category_l}s"
91
- comment_f = "%-#{comment_l}s"
92
-
93
- # Create a table header.
94
- header = ''
95
- header << '#' * entries_l << ' '
96
- header << 'Date ' << ' ' * 7
97
- header << title_f % 'Title' << ' '
98
- header << revenue_f % 'Revenue' << ' '
99
- header << expense_f % 'Expense' << ' '
100
- header << balance_f % 'Balance'
101
- if has_category_col
102
- header << ' ' << category_f % 'Category'
103
- end
104
- if has_comment_col
105
- header << ' ' << comment_f % 'Comment'
106
- end
107
-
108
- header_l = header.length
109
- header.sub!(/ +$/, '')
110
-
111
- # Print table header.
112
- puts header
113
- puts '-' * header_l
114
-
115
- # Sums
116
- revenue_total = 0.0
117
- expense_total = 0.0
118
- balance_total = 0.0
119
-
120
- # Do not repeat the same date over and over again.
121
- previous_date = ''
122
-
123
- entry_no = 0
124
-
125
- # Iterate all days.
126
- entries.sort.each do |day_name, day_items|
127
- # Iterate all entries of a day.
128
- day_items.each do |entry|
129
- entry_no += 1
130
-
131
- title = entry['title']
132
- if title.length >= 25
133
- title = title[0, 22] << '...'
134
- end
135
-
136
- revenue_total += entry['revenue']
137
- expense_total += entry['expense']
138
- balance_total += entry['balance']
139
-
140
- category = entry['category'] == 'default' ? '' : entry['category']
141
-
142
- comment = entry['comment']
143
- if comment.length >= 25
144
- comment = comment[0, 22] << '...'
145
- end
146
-
147
- out = ''
148
- out << entries_f % entry_no
149
- out << ' ' << '%10s' % (entry['date'] == previous_date ? '' : entry['date'])
150
- out << ' ' << title_f % title
151
- out << ' ' << revenue_f % (NUMBER_FORMAT % entry['revenue'])
152
- out << ' ' << expense_f % (NUMBER_FORMAT % entry['expense'])
153
- out << ' ' << balance_f % (NUMBER_FORMAT % entry['balance'])
154
- out << ' ' << category_f % category if has_category_col
155
- out << ' ' << comment_f % comment if has_comment_col
156
-
157
- out.sub!(/ +$/, '')
158
- puts out
159
-
160
- previous_date = entry['date']
161
- end
162
- end
163
- puts
164
-
165
- out = ''
166
- out << ' ' * (12 + entries_l)
167
- out << ' ' << title_f % 'TOTAL'
168
- out << ' ' << revenue_f % (NUMBER_FORMAT % revenue_total)
169
- out << ' ' << expense_f % (NUMBER_FORMAT % expense_total)
170
- out << ' ' << balance_f % (NUMBER_FORMAT % balance_total)
171
- puts out
172
- end
173
-
174
- end
175
-
3
+
4
+ # List entries. Per default this command lists all entries of today.
5
+ # @TODO Use terminal-table for output? https://github.com/tj/terminal-table
6
+ class ListCommand < Command
7
+
8
+ NAME = 'list'
9
+
10
+ def run
11
+ puts
12
+
13
+ wallet = Wallet.new(@options[:wallet_path])
14
+ entries = wallet.entries(@options[:entry_date], @options[:entry_category].to_s)
15
+
16
+ # Get max length of all columns.
17
+ entries_l = entries
18
+ .map{ |day_name, day_items| day_items.count }
19
+ .inject{ |sum, n| sum + n }
20
+ .to_s
21
+ .length
22
+ title_l = entries
23
+ .map{ |month_item| month_item[1].map{ |day_item| day_item['title'].length }}
24
+ .flatten
25
+ .max
26
+ .to_i
27
+ revenue_l = entries
28
+ .map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['revenue']).length } }
29
+ .flatten
30
+ .max
31
+ .to_i
32
+ expense_l = entries
33
+ .map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['expense']).length } }
34
+ .flatten
35
+ .max
36
+ .to_i
37
+ balance_l = entries
38
+ .map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['balance']).length } }
39
+ .flatten
40
+ .max
41
+ .to_i
42
+ category_l = entries
43
+ .map{ |month_item| month_item[1].map{ |day_item| day_item['category'].length } }
44
+ .flatten
45
+ .max
46
+ .to_i
47
+ comment_l = entries
48
+ .map{ |month_item| month_item[1].map{ |day_item| day_item['comment'].length } }
49
+ .flatten
50
+ .max
51
+ .to_i
52
+
53
+ has_category_col = entries.map{ |month_item| month_item[1].map{ |day_item| day_item['category'] } }.flatten.select{ |i| i != 'default' }.count > 0
54
+ has_comment_col = entries
55
+ .map{ |month_item| month_item[1].map{ |day_item| day_item['comment'] } }
56
+ .flatten
57
+ .select{ |i| i != '' }
58
+ .count > 0
59
+
60
+ # Limit some columns to a maximum length.
61
+ if title_l < 6
62
+ title_l = 6
63
+ end
64
+ if title_l > 25
65
+ title_l = 25
66
+ end
67
+
68
+ if revenue_l < 7
69
+ revenue_l = 7
70
+ end
71
+ if expense_l < 7
72
+ expense_l = 7
73
+ end
74
+ if balance_l < 7
75
+ balance_l = 7
76
+ end
77
+ if category_l < 8
78
+ category_l = 8
79
+ end
80
+ if comment_l > 25
81
+ comment_l = 25
82
+ end
83
+
84
+ # Format String for each column.
85
+ entries_f = "%#{entries_l}s"
86
+ title_f = "%-#{title_l}s"
87
+ revenue_f = "%#{revenue_l}s"
88
+ expense_f = "%#{expense_l}s"
89
+ balance_f = "%#{balance_l}s"
90
+ category_f = "%-#{category_l}s"
91
+ comment_f = "%-#{comment_l}s"
92
+
93
+ # Create a table header.
94
+ header = ''
95
+ header << '#' * entries_l << ' '
96
+ header << 'Date ' << ' ' * 7
97
+ header << title_f % 'Title' << ' '
98
+ header << revenue_f % 'Revenue' << ' '
99
+ header << expense_f % 'Expense' << ' '
100
+ header << balance_f % 'Balance'
101
+ if has_category_col
102
+ header << ' ' << category_f % 'Category'
103
+ end
104
+ if has_comment_col
105
+ header << ' ' << comment_f % 'Comment'
106
+ end
107
+
108
+ header_l = header.length
109
+ header.sub!(/ +$/, '')
110
+
111
+ # Print table header.
112
+ puts header
113
+ puts '-' * header_l
114
+
115
+ # Sums
116
+ revenue_total = 0.0
117
+ expense_total = 0.0
118
+ balance_total = 0.0
119
+
120
+ entry_no = 0
121
+
122
+ # Iterate all days.
123
+ entries.sort.each do |day_name, day_items|
124
+ # Iterate all entries of a day.
125
+ day_items.each do |entry|
126
+ entry_no += 1
127
+
128
+ title = entry['title']
129
+ if title.length >= 25
130
+ title = title[0, 22] << '...'
131
+ end
132
+
133
+ revenue_total += entry['revenue']
134
+ expense_total += entry['expense']
135
+ balance_total += entry['balance']
136
+
137
+ category = entry['category'] == 'default' ? '' : entry['category']
138
+
139
+ comment = entry['comment']
140
+ if comment.length >= 25
141
+ comment = comment[0, 22] << '...'
142
+ end
143
+
144
+ out = ''
145
+ out << entries_f % entry_no
146
+ out << ' ' << '%10s' % entry['date']
147
+ out << ' ' << title_f % title
148
+ out << ' ' << revenue_f % (NUMBER_FORMAT % entry['revenue'])
149
+ out << ' ' << expense_f % (NUMBER_FORMAT % entry['expense'])
150
+ out << ' ' << balance_f % (NUMBER_FORMAT % entry['balance'])
151
+ out << ' ' << category_f % category if has_category_col
152
+ out << ' ' << comment_f % comment if has_comment_col
153
+
154
+ out.sub!(/ +$/, '')
155
+ puts out
156
+ end
157
+ end
158
+ puts
159
+
160
+ out = ''
161
+ out << ' ' * (12 + entries_l)
162
+ out << ' ' << title_f % 'TOTAL'
163
+ out << ' ' << revenue_f % (NUMBER_FORMAT % revenue_total)
164
+ out << ' ' << expense_f % (NUMBER_FORMAT % expense_total)
165
+ out << ' ' << balance_f % (NUMBER_FORMAT % balance_total)
166
+ puts out
167
+ end
168
+
169
+ end
170
+
176
171
  end