thefox-wallet 0.9.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Makefile.common +3 -5
- data/bin/wallet +8 -277
- data/lib/wallet/command.rb +54 -0
- data/lib/wallet/command_add.rb +70 -0
- data/lib/wallet/command_categories.rb +17 -0
- data/lib/wallet/command_csv.rb +53 -0
- data/lib/wallet/command_html.rb +17 -0
- data/lib/wallet/command_list.rb +155 -0
- data/lib/wallet/version.rb +2 -2
- data/lib/wallet.rb +6 -0
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd5ea869e14eae3be3cbab943cf67509350237a2
|
4
|
+
data.tar.gz: e21e861a5c49337b1f383cb776c0e1732fb90ebd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8250d333120eea0261af00cc3d84c58f62334b354be89de4d8e2e6209f95cbb97581b8b760d3d230f8f8c574d2201519e31c3e8f62df376b8b9bdc1872fe6635
|
7
|
+
data.tar.gz: 28a6c2edca9e17e80dc4c63f562b9495f8bcf3919b7e4f1b2acd3f74a2677164878fd6486e2279f9ceca798f0ce333a476bd88e9e041bf8b8b6b3651f9ad0380
|
data/.gitignore
CHANGED
data/Makefile.common
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
|
2
2
|
# Ruby Common Big
|
3
|
-
# 2016-
|
3
|
+
# 2016-05-20
|
4
4
|
|
5
5
|
MV = mv -nv
|
6
|
-
RM = rm -
|
6
|
+
RM = rm -rfd
|
7
7
|
MKDIR = mkdir -p
|
8
8
|
CHMOD = chmod
|
9
9
|
BUNDLER = bundle
|
@@ -36,9 +36,7 @@ update:
|
|
36
36
|
|
37
37
|
.PHONY: clean
|
38
38
|
clean:
|
39
|
-
$(RM) .bundle
|
40
|
-
$(RM) .setup
|
41
|
-
$(RM) Gemfile.lock
|
39
|
+
$(RM) .bundle .setup Gemfile.lock
|
42
40
|
|
43
41
|
.PHONY: release
|
44
42
|
release: | releases
|
data/bin/wallet
CHANGED
@@ -1,26 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'pp'
|
4
3
|
require 'optparse'
|
5
4
|
require 'wallet'
|
6
5
|
require 'tempfile'
|
7
6
|
|
8
|
-
options = {
|
9
|
-
:wallet_path => 'wallet',
|
10
|
-
|
11
|
-
:entry_title => nil,
|
12
|
-
:entry_date => Date.today.to_s,
|
13
|
-
#:entry_end_date => nil,
|
14
|
-
:entry_revenue => 0.0,
|
15
|
-
:entry_expense => 0.0,
|
16
|
-
:entry_category => nil,
|
17
|
-
:entry_comment => nil,
|
18
|
-
|
19
|
-
:is_import => false,
|
20
|
-
:is_export => false,
|
21
|
-
:path => nil,
|
22
|
-
:is_interactively => false,
|
23
|
-
}
|
7
|
+
options = {}
|
24
8
|
opts = OptionParser.new do |o|
|
25
9
|
o.banner = 'Usage: wallet <command> [options]'
|
26
10
|
o.separator('')
|
@@ -97,265 +81,12 @@ opts = OptionParser.new do |o|
|
|
97
81
|
end
|
98
82
|
ARGV << '-h' if ARGV.count == 0
|
99
83
|
commands = opts.parse(ARGV)
|
100
|
-
|
101
|
-
|
102
|
-
#pp commands
|
103
|
-
#pp command
|
84
|
+
command_name = commands.shift
|
104
85
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
print "title: [#{options[:entry_title]}] "
|
112
|
-
title_t = STDIN.gets.strip
|
113
|
-
if title_t.length > 0
|
114
|
-
options[:entry_title] = title_t
|
115
|
-
end
|
116
|
-
|
117
|
-
print "date: [#{options[:entry_date]}] "
|
118
|
-
date_t = STDIN.gets.strip
|
119
|
-
if date_t.length > 0
|
120
|
-
options[:entry_date] = date_t
|
121
|
-
end
|
122
|
-
|
123
|
-
print "revenue: [#{options[:entry_revenue]}] "
|
124
|
-
revenue_t = STDIN.gets.strip
|
125
|
-
if revenue_t.length > 0
|
126
|
-
options[:entry_revenue] = revenue_t.to_s.sub(/,/, '.').to_f.round(TheFox::Wallet::NUMBER_ROUND).abs
|
127
|
-
end
|
128
|
-
|
129
|
-
print "expense: [#{options[:entry_expense]}] "
|
130
|
-
expense_t = STDIN.gets.strip
|
131
|
-
if expense_t.length > 0
|
132
|
-
options[:entry_expense] = -expense_t.to_s.sub(/,/, '.').to_f.round(TheFox::Wallet::NUMBER_ROUND).abs
|
133
|
-
end
|
134
|
-
|
135
|
-
print "category: [#{options[:entry_category]}] "
|
136
|
-
category_t = STDIN.gets.strip
|
137
|
-
if category_t.length > 0
|
138
|
-
options[:entry_category] = category_t
|
139
|
-
end
|
140
|
-
|
141
|
-
print "comment: [#{options[:entry_comment]}] "
|
142
|
-
comment_t = STDIN.gets.strip
|
143
|
-
if comment_t.length > 0
|
144
|
-
options[:entry_comment] = comment_t
|
145
|
-
end
|
146
|
-
|
147
|
-
puts '-' * 20
|
148
|
-
end
|
149
|
-
|
150
|
-
if options[:entry_title].nil?
|
151
|
-
puts "ERROR: Option --title is required for command '#{command}'"
|
152
|
-
exit 1
|
153
|
-
end
|
154
|
-
|
155
|
-
puts "title: '#{options[:entry_title]}'"
|
156
|
-
puts "date: " + Date.parse(options[:entry_date]).to_s
|
157
|
-
puts "revenue: " + TheFox::Wallet::NUMBER_FORMAT % options[:entry_revenue]
|
158
|
-
puts "expense: " + TheFox::Wallet::NUMBER_FORMAT % options[:entry_expense]
|
159
|
-
puts "balance: " + TheFox::Wallet::NUMBER_FORMAT % [options[:entry_revenue] + options[:entry_expense]]
|
160
|
-
puts "category: #{options[:entry_category]}"
|
161
|
-
puts "comment: '#{options[:entry_comment]}'"
|
162
|
-
|
163
|
-
entry = TheFox::Wallet::Entry.new(options[:entry_title], options[:entry_date], options[:entry_revenue], options[:entry_expense], options[:entry_category], options[:entry_comment])
|
164
|
-
wallet = TheFox::Wallet::Wallet.new(options[:wallet_path])
|
165
|
-
wallet.add(entry)
|
166
|
-
when 'list'
|
167
|
-
puts
|
168
|
-
|
169
|
-
wallet = TheFox::Wallet::Wallet.new(options[:wallet_path])
|
170
|
-
entries = wallet.entries(options[:entry_date], options[:entry_category].to_s)
|
171
|
-
#entries = wallet.entries(options[:entry_date], options[:entry_end_date], options[:entry_category].to_s)
|
172
|
-
|
173
|
-
entries_l = entries
|
174
|
-
.map{ |day_name, day_items| day_items.count }
|
175
|
-
.inject{ |sum, n| sum + n }
|
176
|
-
.to_s
|
177
|
-
.length
|
178
|
-
title_l = entries
|
179
|
-
.map{ |month_item| month_item[1].map{ |day_item| day_item['title'].length }}
|
180
|
-
.flatten
|
181
|
-
.max
|
182
|
-
.to_i
|
183
|
-
revenue_l = entries
|
184
|
-
.map{ |month_item| month_item[1].map{ |day_item| (TheFox::Wallet::NUMBER_FORMAT % day_item['revenue']).length } }
|
185
|
-
.flatten
|
186
|
-
.max
|
187
|
-
.to_i
|
188
|
-
expense_l = entries
|
189
|
-
.map{ |month_item| month_item[1].map{ |day_item| (TheFox::Wallet::NUMBER_FORMAT % day_item['expense']).length } }
|
190
|
-
.flatten
|
191
|
-
.max
|
192
|
-
.to_i
|
193
|
-
balance_l = entries
|
194
|
-
.map{ |month_item| month_item[1].map{ |day_item| (TheFox::Wallet::NUMBER_FORMAT % day_item['balance']).length } }
|
195
|
-
.flatten
|
196
|
-
.max
|
197
|
-
.to_i
|
198
|
-
category_l = entries
|
199
|
-
.map{ |month_item| month_item[1].map{ |day_item| day_item['category'].length } }
|
200
|
-
.flatten
|
201
|
-
.max
|
202
|
-
.to_i
|
203
|
-
comment_l = entries
|
204
|
-
.map{ |month_item| month_item[1].map{ |day_item| day_item['comment'].length } }
|
205
|
-
.flatten
|
206
|
-
.max
|
207
|
-
.to_i
|
208
|
-
|
209
|
-
has_category_col = entries.map{ |month_item| month_item[1].map{ |day_item| day_item['category'] } }.flatten.select{ |i| i != 'default' }.count > 0
|
210
|
-
has_comment_col = entries
|
211
|
-
.map{ |month_item| month_item[1].map{ |day_item| day_item['comment'] } }
|
212
|
-
.flatten
|
213
|
-
.select{ |i| i != '' }
|
214
|
-
.count > 0
|
215
|
-
|
216
|
-
if title_l < 6
|
217
|
-
title_l = 6
|
218
|
-
end
|
219
|
-
if title_l > 25
|
220
|
-
title_l = 25
|
221
|
-
end
|
222
|
-
|
223
|
-
if revenue_l < 7
|
224
|
-
revenue_l = 7
|
225
|
-
end
|
226
|
-
if expense_l < 7
|
227
|
-
expense_l = 7
|
228
|
-
end
|
229
|
-
if balance_l < 7
|
230
|
-
balance_l = 7
|
231
|
-
end
|
232
|
-
if category_l < 8
|
233
|
-
category_l = 8
|
234
|
-
end
|
235
|
-
if comment_l > 25
|
236
|
-
comment_l = 25
|
237
|
-
end
|
238
|
-
|
239
|
-
entries_f = '%' + entries_l.to_s + 's'
|
240
|
-
title_f = '%-' + title_l.to_s + 's'
|
241
|
-
revenue_f = '%' + revenue_l.to_s + 's'
|
242
|
-
expense_f = '%' + expense_l.to_s + 's'
|
243
|
-
balance_f = '%' + balance_l.to_s + 's'
|
244
|
-
category_f = '%-' + category_l.to_s + 's'
|
245
|
-
comment_f = '%-' + comment_l.to_s + 's'
|
246
|
-
|
247
|
-
header = ''
|
248
|
-
header += '#' * entries_l + ' '
|
249
|
-
header += 'Date ' + ' ' * 7
|
250
|
-
header += title_f % 'Title' + ' '
|
251
|
-
header += revenue_f % 'Revenue' + ' '
|
252
|
-
header += expense_f % 'Expense' + ' '
|
253
|
-
header += balance_f % 'Balance'
|
254
|
-
header += ' ' + category_f % 'Category' if has_category_col
|
255
|
-
header += ' ' + comment_f % 'Comment' if has_comment_col
|
256
|
-
|
257
|
-
header_l = header.length
|
258
|
-
header.sub!(/ +$/, '')
|
259
|
-
puts header
|
260
|
-
puts '-' * header_l
|
261
|
-
|
262
|
-
revenue_total = 0.0
|
263
|
-
expense_total = 0.0
|
264
|
-
balance_total = 0.0
|
265
|
-
previous_date = ''
|
266
|
-
entry_no = 0
|
267
|
-
entries.sort.each do |day_name, day_items|
|
268
|
-
day_items.each do |entry|
|
269
|
-
entry_no += 1
|
270
|
-
|
271
|
-
title = entry['title']
|
272
|
-
title = title[0, 22] + '...' if title.length >= 25
|
273
|
-
|
274
|
-
revenue_total += entry['revenue']
|
275
|
-
expense_total += entry['expense']
|
276
|
-
balance_total += entry['balance']
|
277
|
-
|
278
|
-
category = entry['category'] == 'default' ? '' : entry['category']
|
279
|
-
has_category = category != ''
|
280
|
-
|
281
|
-
comment = entry['comment']
|
282
|
-
comment = comment[0, 22] + '...' if comment.length >= 25
|
283
|
-
|
284
|
-
out = ''
|
285
|
-
out += entries_f % entry_no
|
286
|
-
out += ' ' + '%10s' % (entry['date'] == previous_date ? '' : entry['date'])
|
287
|
-
out += ' ' + title_f % title
|
288
|
-
out += ' ' + revenue_f % (TheFox::Wallet::NUMBER_FORMAT % entry['revenue'])
|
289
|
-
out += ' ' + expense_f % (TheFox::Wallet::NUMBER_FORMAT % entry['expense'])
|
290
|
-
out += ' ' + balance_f % (TheFox::Wallet::NUMBER_FORMAT % entry['balance'])
|
291
|
-
out += ' ' + category_f % category if has_category_col
|
292
|
-
out += ' ' + comment_f % comment if has_comment_col
|
293
|
-
|
294
|
-
out.sub!(/ +$/, '')
|
295
|
-
puts out
|
296
|
-
|
297
|
-
previous_date = entry['date']
|
298
|
-
end
|
299
|
-
end
|
300
|
-
puts
|
301
|
-
|
302
|
-
out = ''
|
303
|
-
out += ' ' * (12 + entries_l)
|
304
|
-
out += ' ' + title_f % 'TOTAL'
|
305
|
-
out += ' ' + revenue_f % (TheFox::Wallet::NUMBER_FORMAT % revenue_total)
|
306
|
-
out += ' ' + expense_f % (TheFox::Wallet::NUMBER_FORMAT % expense_total)
|
307
|
-
out += ' ' + balance_f % (TheFox::Wallet::NUMBER_FORMAT % balance_total)
|
308
|
-
puts out
|
309
|
-
when 'categories'
|
310
|
-
wallet = TheFox::Wallet::Wallet.new(options[:wallet_path])
|
311
|
-
categories = wallet.categories
|
312
|
-
puts "categories: #{categories.count}"
|
313
|
-
puts "\t" + categories.join("\n\t")
|
314
|
-
when 'html'
|
315
|
-
wallet = TheFox::Wallet::Wallet.new(options[:wallet_path])
|
316
|
-
puts 'generate html to ' + wallet.html_path + ' ...'
|
317
|
-
wallet.gen_html
|
318
|
-
puts 'generate html done'
|
319
|
-
when 'csv'
|
320
|
-
if options[:is_interactively]
|
321
|
-
vi_file = Tempfile.create('wallet-vi-import', '/tmp')
|
322
|
-
vi_file.puts('# This is a comment line.')
|
323
|
-
vi_file.puts('# Date,Title,Revenue,Expense,Category,Comment')
|
324
|
-
vi_file.puts('# Date,Title,Expense')
|
325
|
-
vi_file.puts
|
326
|
-
vi_file.puts
|
327
|
-
vi_file.close
|
328
|
-
|
329
|
-
puts 'cwd: ' + Dir.pwd
|
330
|
-
puts 'editor: ' + ENV['EDITOR']
|
331
|
-
puts 'file: ' + vi_file.path
|
332
|
-
|
333
|
-
system("#{ENV['EDITOR']} #{vi_file.path}")
|
334
|
-
system("grep -v '#' #{vi_file.path} | grep -v ^$ > #{vi_file.path}.ok")
|
335
|
-
|
336
|
-
options[:path] = "#{vi_file.path}.ok"
|
337
|
-
File.unlink(vi_file.path)
|
338
|
-
end
|
339
|
-
|
340
|
-
if options[:path].nil?
|
341
|
-
puts "ERROR: Option --path is required for command '#{command}'"
|
342
|
-
exit 1
|
343
|
-
end
|
344
|
-
|
345
|
-
wallet = TheFox::Wallet::Wallet.new(options[:wallet_path])
|
346
|
-
|
347
|
-
if options[:is_import] || !options[:is_export]
|
348
|
-
puts "import csv #{options[:path]} ..."
|
349
|
-
wallet.import_csv_file(options[:path])
|
350
|
-
puts "import csv #{options[:path]} done"
|
351
|
-
|
352
|
-
if options[:is_interactively]
|
353
|
-
puts "delete #{options[:path]}"
|
354
|
-
File.unlink(options[:path])
|
355
|
-
end
|
356
|
-
elsif options[:is_export]
|
357
|
-
puts "export csv #{options[:path]} ..."
|
358
|
-
wallet.export_csv_file(options[:path])
|
359
|
-
puts "export csv #{options[:path]} done"
|
360
|
-
end
|
86
|
+
begin
|
87
|
+
command = TheFox::Wallet::Command.create_by_name(command_name, options)
|
88
|
+
command.run
|
89
|
+
rescue Exception => e
|
90
|
+
puts "ERROR: #{e}"
|
91
|
+
exit 1
|
361
92
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
require 'date'
|
3
|
+
#require 'pp'
|
4
|
+
|
5
|
+
module TheFox::Wallet
|
6
|
+
|
7
|
+
class Command
|
8
|
+
|
9
|
+
NAME = 'default'
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = options || {}
|
13
|
+
@options[:wallet_path] ||= 'wallet'
|
14
|
+
@options[:entry_title] ||= nil
|
15
|
+
@options[:entry_date] ||= Date.today.to_s
|
16
|
+
@options[:entry_revenue] ||= 0.0
|
17
|
+
@options[:entry_expense] ||= 0.0
|
18
|
+
@options[:entry_category] ||= nil
|
19
|
+
@options[:entry_comment] ||= nil
|
20
|
+
@options[:is_import] ||= false
|
21
|
+
@options[:is_export] ||= false
|
22
|
+
@options[:path] ||= nil
|
23
|
+
@options[:is_interactively] ||= false
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.create_by_name(name, options)
|
30
|
+
classes = [
|
31
|
+
AddCommand,
|
32
|
+
ListCommand,
|
33
|
+
CategoriesCommand,
|
34
|
+
HtmlCommand,
|
35
|
+
CsvCommand,
|
36
|
+
]
|
37
|
+
|
38
|
+
classes.each do |cclass|
|
39
|
+
#puts "class: '#{cclass::NAME}' '#{cclass.is_matching_class(name)}'"
|
40
|
+
if cclass.is_matching_class(name)
|
41
|
+
return cclass.new(options)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
raise "Unknown command '#{name}'"
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.is_matching_class(name)
|
49
|
+
name == self::NAME
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
|
2
|
+
module TheFox::Wallet
|
3
|
+
class AddCommand < Command
|
4
|
+
|
5
|
+
NAME = 'add'
|
6
|
+
|
7
|
+
def run
|
8
|
+
if @options[:entry_category].nil?
|
9
|
+
@options[:entry_category] = 'default'
|
10
|
+
end
|
11
|
+
if @options[:is_interactively]
|
12
|
+
print "title: [#{@options[:entry_title]}] "
|
13
|
+
title_t = STDIN.gets.strip
|
14
|
+
if title_t.length > 0
|
15
|
+
@options[:entry_title] = title_t
|
16
|
+
end
|
17
|
+
|
18
|
+
print "date: [#{@options[:entry_date]}] "
|
19
|
+
date_t = STDIN.gets.strip
|
20
|
+
if date_t.length > 0
|
21
|
+
@options[:entry_date] = date_t
|
22
|
+
end
|
23
|
+
|
24
|
+
print "revenue: [#{@options[:entry_revenue]}] "
|
25
|
+
revenue_t = STDIN.gets.strip
|
26
|
+
if revenue_t.length > 0
|
27
|
+
@options[:entry_revenue] = eval(revenue_t).to_s.sub(/,/, '.').to_f.round(NUMBER_ROUND).abs
|
28
|
+
end
|
29
|
+
|
30
|
+
print "expense: [#{@options[:entry_expense]}] "
|
31
|
+
expense_t = STDIN.gets.strip
|
32
|
+
if expense_t.length > 0
|
33
|
+
@options[:entry_expense] = -eval(expense_t).to_s.sub(/,/, '.').to_f.round(NUMBER_ROUND).abs
|
34
|
+
end
|
35
|
+
|
36
|
+
print "category: [#{@options[:entry_category]}] "
|
37
|
+
category_t = STDIN.gets.strip
|
38
|
+
if category_t.length > 0
|
39
|
+
@options[:entry_category] = category_t
|
40
|
+
end
|
41
|
+
|
42
|
+
print "comment: [#{@options[:entry_comment]}] "
|
43
|
+
comment_t = STDIN.gets.strip
|
44
|
+
if comment_t.length > 0
|
45
|
+
@options[:entry_comment] = comment_t
|
46
|
+
end
|
47
|
+
|
48
|
+
puts '-' * 20
|
49
|
+
end
|
50
|
+
|
51
|
+
if @options[:entry_title].nil?
|
52
|
+
raise "Option --title is required for command '#{NAME}'"
|
53
|
+
end
|
54
|
+
|
55
|
+
puts "title: '#{@options[:entry_title]}'"
|
56
|
+
puts "date: " + Date.parse(@options[:entry_date]).to_s
|
57
|
+
puts "revenue: " + NUMBER_FORMAT % @options[:entry_revenue]
|
58
|
+
puts "expense: " + NUMBER_FORMAT % @options[:entry_expense]
|
59
|
+
puts "balance: " + NUMBER_FORMAT % [@options[:entry_revenue] + @options[:entry_expense]]
|
60
|
+
puts "category: #{@options[:entry_category]}"
|
61
|
+
puts "comment: '#{@options[:entry_comment]}'"
|
62
|
+
|
63
|
+
entry = Entry.new(@options[:entry_title], @options[:entry_date], @options[:entry_revenue], @options[:entry_expense], @options[:entry_category], @options[:entry_comment])
|
64
|
+
wallet = Wallet.new(@options[:wallet_path])
|
65
|
+
wallet.add(entry)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
module TheFox::Wallet
|
3
|
+
|
4
|
+
class CategoriesCommand < Command
|
5
|
+
|
6
|
+
NAME = 'categories'
|
7
|
+
|
8
|
+
def run
|
9
|
+
wallet = Wallet.new(@options[:wallet_path])
|
10
|
+
categories = wallet.categories
|
11
|
+
puts "categories: #{categories.count}"
|
12
|
+
puts "\t" + categories.join("\n\t")
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
module TheFox::Wallet
|
3
|
+
|
4
|
+
class CsvCommand < Command
|
5
|
+
|
6
|
+
NAME = 'csv'
|
7
|
+
|
8
|
+
def run
|
9
|
+
if @options[:is_interactively]
|
10
|
+
vi_file = Tempfile.create('wallet-vi-import', '/tmp')
|
11
|
+
vi_file.puts('# This is a comment line.')
|
12
|
+
vi_file.puts('# Date,Title,Revenue,Expense,Category,Comment')
|
13
|
+
vi_file.puts('# Date,Title,Expense')
|
14
|
+
vi_file.puts
|
15
|
+
vi_file.puts
|
16
|
+
vi_file.close
|
17
|
+
|
18
|
+
puts 'cwd: ' + Dir.pwd
|
19
|
+
puts 'editor: ' + ENV['EDITOR']
|
20
|
+
puts 'file: ' + vi_file.path
|
21
|
+
|
22
|
+
system("#{ENV['EDITOR']} #{vi_file.path}")
|
23
|
+
system("grep -v '#' #{vi_file.path} | grep -v ^$ > #{vi_file.path}.ok")
|
24
|
+
|
25
|
+
@options[:path] = "#{vi_file.path}.ok"
|
26
|
+
File.unlink(vi_file.path)
|
27
|
+
end
|
28
|
+
|
29
|
+
if @options[:path].nil?
|
30
|
+
raise "Option --path is required for command '#{NAME}'"
|
31
|
+
end
|
32
|
+
|
33
|
+
wallet = Wallet.new(@options[:wallet_path])
|
34
|
+
|
35
|
+
if @options[:is_import] || !@options[:is_export]
|
36
|
+
puts "import csv #{@options[:path]} ..."
|
37
|
+
wallet.import_csv_file(@options[:path])
|
38
|
+
puts "import csv #{@options[:path]} done"
|
39
|
+
|
40
|
+
if @options[:is_interactively]
|
41
|
+
puts "delete #{@options[:path]}"
|
42
|
+
File.unlink(@options[:path])
|
43
|
+
end
|
44
|
+
elsif @options[:is_export]
|
45
|
+
puts "export csv #{@options[:path]} ..."
|
46
|
+
wallet.export_csv_file(@options[:path])
|
47
|
+
puts "export csv #{@options[:path]} done"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
module TheFox::Wallet
|
3
|
+
|
4
|
+
class HtmlCommand < Command
|
5
|
+
|
6
|
+
NAME = 'html'
|
7
|
+
|
8
|
+
def run
|
9
|
+
wallet = Wallet.new(@options[:wallet_path])
|
10
|
+
puts 'generate html to ' + wallet.html_path + ' ...'
|
11
|
+
wallet.gen_html
|
12
|
+
puts 'generate html done'
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
|
2
|
+
module TheFox::Wallet
|
3
|
+
|
4
|
+
class ListCommand < Command
|
5
|
+
|
6
|
+
NAME = 'list'
|
7
|
+
|
8
|
+
def run
|
9
|
+
puts
|
10
|
+
|
11
|
+
wallet = Wallet.new(@options[:wallet_path])
|
12
|
+
entries = wallet.entries(@options[:entry_date], @options[:entry_category].to_s)
|
13
|
+
#entries = wallet.entries(@options[:entry_date], @options[:entry_end_date], @options[:entry_category].to_s)
|
14
|
+
|
15
|
+
entries_l = entries
|
16
|
+
.map{ |day_name, day_items| day_items.count }
|
17
|
+
.inject{ |sum, n| sum + n }
|
18
|
+
.to_s
|
19
|
+
.length
|
20
|
+
title_l = entries
|
21
|
+
.map{ |month_item| month_item[1].map{ |day_item| day_item['title'].length }}
|
22
|
+
.flatten
|
23
|
+
.max
|
24
|
+
.to_i
|
25
|
+
revenue_l = entries
|
26
|
+
.map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['revenue']).length } }
|
27
|
+
.flatten
|
28
|
+
.max
|
29
|
+
.to_i
|
30
|
+
expense_l = entries
|
31
|
+
.map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['expense']).length } }
|
32
|
+
.flatten
|
33
|
+
.max
|
34
|
+
.to_i
|
35
|
+
balance_l = entries
|
36
|
+
.map{ |month_item| month_item[1].map{ |day_item| (NUMBER_FORMAT % day_item['balance']).length } }
|
37
|
+
.flatten
|
38
|
+
.max
|
39
|
+
.to_i
|
40
|
+
category_l = entries
|
41
|
+
.map{ |month_item| month_item[1].map{ |day_item| day_item['category'].length } }
|
42
|
+
.flatten
|
43
|
+
.max
|
44
|
+
.to_i
|
45
|
+
comment_l = entries
|
46
|
+
.map{ |month_item| month_item[1].map{ |day_item| day_item['comment'].length } }
|
47
|
+
.flatten
|
48
|
+
.max
|
49
|
+
.to_i
|
50
|
+
|
51
|
+
has_category_col = entries.map{ |month_item| month_item[1].map{ |day_item| day_item['category'] } }.flatten.select{ |i| i != 'default' }.count > 0
|
52
|
+
has_comment_col = entries
|
53
|
+
.map{ |month_item| month_item[1].map{ |day_item| day_item['comment'] } }
|
54
|
+
.flatten
|
55
|
+
.select{ |i| i != '' }
|
56
|
+
.count > 0
|
57
|
+
|
58
|
+
if title_l < 6
|
59
|
+
title_l = 6
|
60
|
+
end
|
61
|
+
if title_l > 25
|
62
|
+
title_l = 25
|
63
|
+
end
|
64
|
+
|
65
|
+
if revenue_l < 7
|
66
|
+
revenue_l = 7
|
67
|
+
end
|
68
|
+
if expense_l < 7
|
69
|
+
expense_l = 7
|
70
|
+
end
|
71
|
+
if balance_l < 7
|
72
|
+
balance_l = 7
|
73
|
+
end
|
74
|
+
if category_l < 8
|
75
|
+
category_l = 8
|
76
|
+
end
|
77
|
+
if comment_l > 25
|
78
|
+
comment_l = 25
|
79
|
+
end
|
80
|
+
|
81
|
+
entries_f = '%' + entries_l.to_s + 's'
|
82
|
+
title_f = '%-' + title_l.to_s + 's'
|
83
|
+
revenue_f = '%' + revenue_l.to_s + 's'
|
84
|
+
expense_f = '%' + expense_l.to_s + 's'
|
85
|
+
balance_f = '%' + balance_l.to_s + 's'
|
86
|
+
category_f = '%-' + category_l.to_s + 's'
|
87
|
+
comment_f = '%-' + comment_l.to_s + 's'
|
88
|
+
|
89
|
+
header = ''
|
90
|
+
header += '#' * entries_l + ' '
|
91
|
+
header += 'Date ' + ' ' * 7
|
92
|
+
header += title_f % 'Title' + ' '
|
93
|
+
header += revenue_f % 'Revenue' + ' '
|
94
|
+
header += expense_f % 'Expense' + ' '
|
95
|
+
header += balance_f % 'Balance'
|
96
|
+
header += ' ' + category_f % 'Category' if has_category_col
|
97
|
+
header += ' ' + comment_f % 'Comment' if has_comment_col
|
98
|
+
|
99
|
+
header_l = header.length
|
100
|
+
header.sub!(/ +$/, '')
|
101
|
+
puts header
|
102
|
+
puts '-' * header_l
|
103
|
+
|
104
|
+
revenue_total = 0.0
|
105
|
+
expense_total = 0.0
|
106
|
+
balance_total = 0.0
|
107
|
+
previous_date = ''
|
108
|
+
entry_no = 0
|
109
|
+
entries.sort.each do |day_name, day_items|
|
110
|
+
day_items.each do |entry|
|
111
|
+
entry_no += 1
|
112
|
+
|
113
|
+
title = entry['title']
|
114
|
+
title = title[0, 22] + '...' if title.length >= 25
|
115
|
+
|
116
|
+
revenue_total += entry['revenue']
|
117
|
+
expense_total += entry['expense']
|
118
|
+
balance_total += entry['balance']
|
119
|
+
|
120
|
+
category = entry['category'] == 'default' ? '' : entry['category']
|
121
|
+
has_category = category != ''
|
122
|
+
|
123
|
+
comment = entry['comment']
|
124
|
+
comment = comment[0, 22] + '...' if comment.length >= 25
|
125
|
+
|
126
|
+
out = ''
|
127
|
+
out += entries_f % entry_no
|
128
|
+
out += ' ' + '%10s' % (entry['date'] == previous_date ? '' : entry['date'])
|
129
|
+
out += ' ' + title_f % title
|
130
|
+
out += ' ' + revenue_f % (NUMBER_FORMAT % entry['revenue'])
|
131
|
+
out += ' ' + expense_f % (NUMBER_FORMAT % entry['expense'])
|
132
|
+
out += ' ' + balance_f % (NUMBER_FORMAT % entry['balance'])
|
133
|
+
out += ' ' + category_f % category if has_category_col
|
134
|
+
out += ' ' + comment_f % comment if has_comment_col
|
135
|
+
|
136
|
+
out.sub!(/ +$/, '')
|
137
|
+
puts out
|
138
|
+
|
139
|
+
previous_date = entry['date']
|
140
|
+
end
|
141
|
+
end
|
142
|
+
puts
|
143
|
+
|
144
|
+
out = ''
|
145
|
+
out += ' ' * (12 + entries_l)
|
146
|
+
out += ' ' + title_f % 'TOTAL'
|
147
|
+
out += ' ' + revenue_f % (NUMBER_FORMAT % revenue_total)
|
148
|
+
out += ' ' + expense_f % (NUMBER_FORMAT % expense_total)
|
149
|
+
out += ' ' + balance_f % (NUMBER_FORMAT % balance_total)
|
150
|
+
puts out
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
data/lib/wallet/version.rb
CHANGED
data/lib/wallet.rb
CHANGED
@@ -2,3 +2,9 @@
|
|
2
2
|
require 'wallet/version'
|
3
3
|
require 'wallet/wallet'
|
4
4
|
require 'wallet/entry'
|
5
|
+
require 'wallet/command'
|
6
|
+
require 'wallet/command_add'
|
7
|
+
require 'wallet/command_list'
|
8
|
+
require 'wallet/command_categories'
|
9
|
+
require 'wallet/command_html'
|
10
|
+
require 'wallet/command_csv'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thefox-wallet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Mayer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -39,6 +39,12 @@ files:
|
|
39
39
|
- README.md
|
40
40
|
- bin/wallet
|
41
41
|
- lib/wallet.rb
|
42
|
+
- lib/wallet/command.rb
|
43
|
+
- lib/wallet/command_add.rb
|
44
|
+
- lib/wallet/command_categories.rb
|
45
|
+
- lib/wallet/command_csv.rb
|
46
|
+
- lib/wallet/command_html.rb
|
47
|
+
- lib/wallet/command_list.rb
|
42
48
|
- lib/wallet/entry.rb
|
43
49
|
- lib/wallet/version.rb
|
44
50
|
- lib/wallet/wallet.rb
|
@@ -67,9 +73,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
73
|
version: '0'
|
68
74
|
requirements: []
|
69
75
|
rubyforge_project:
|
70
|
-
rubygems_version: 2.
|
76
|
+
rubygems_version: 2.5.1
|
71
77
|
signing_key:
|
72
78
|
specification_version: 4
|
73
79
|
summary: Finances Tracking
|
74
80
|
test_files: []
|
75
|
-
has_rdoc:
|