thefox-wallet 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/wallet/wallet.rb CHANGED
@@ -5,40 +5,37 @@ require 'logger'
5
5
  require 'yaml'
6
6
  require 'yaml/store'
7
7
  require 'csv'
8
-
9
- # OpenStruct use to generate HTML.
10
- require 'ostruct'
11
-
8
+ require 'pathname'
9
+ require 'ostruct' # OpenStruct use to generate HTML.
12
10
  # require 'pp'
13
11
 
14
-
15
12
  module TheFox
16
13
  module Wallet
17
14
 
18
15
  class Wallet
19
16
 
20
17
  attr_writer :logger
21
- attr_reader :html_path
18
+ attr_reader :dir_path
22
19
 
23
- def initialize(dir_path = 'wallet')
20
+ def initialize(dir_path = nil)
24
21
  @exit = false
25
22
  @logger = nil
26
- @dir_path = dir_path
27
- @data_path = File.expand_path('data', @dir_path)
28
- @html_path = File.expand_path('html', @dir_path)
29
- @tmp_path = File.expand_path('tmp', @dir_path)
23
+ @dir_path = dir_path || Pathname.new('wallet').expand_path
24
+ @dir_path_basename = @dir_path.basename
25
+ @dir_path_basename_s = @dir_path_basename.to_s
26
+ @data_path = Pathname.new('data').expand_path(@dir_path)
27
+ @tmp_path = Pathname.new('tmp').expand_path(@dir_path)
30
28
 
31
29
  @has_transaction = false
32
30
  @transaction_files = Hash.new
33
31
 
34
32
  @entries_by_ids = nil
35
- @entries_index_file_path = File.expand_path('index.yml', @data_path)
33
+ @entries_index_file_path = Pathname.new('index.yml').expand_path(@data_path)
36
34
  @entries_index = Array.new
37
35
  @entries_index_is_loaded = false
38
36
 
39
37
  Signal.trap('SIGINT') do
40
- puts
41
- puts 'received SIGINT. break ...'
38
+ @logger.warning('received SIGINT. break ...') if @logger
42
39
  @exit = true
43
40
  end
44
41
  end
@@ -48,20 +45,18 @@ module TheFox
48
45
  raise ArgumentError, 'variable must be a Entry instance'
49
46
  end
50
47
 
51
- # puts "add, id #{entry.id}"
52
- # puts "add, is_unique #{is_unique}"
53
- # puts "add, entry_exist? #{entry_exist?(entry)}"
54
- # puts
55
-
56
48
  if is_unique && entry_exist?(entry)
57
49
  return false
58
50
  end
59
51
 
52
+ create_dirs
53
+
60
54
  date = entry.date
61
55
  date_s = date.to_s
62
- dbfile_basename = "month_#{date.strftime('%Y_%m')}.yml"
63
- dbfile_path = File.expand_path(dbfile_basename, @data_path)
64
- tmpfile_path = "#{dbfile_path}.tmp"
56
+ dbfile_basename_s = "month_#{date.strftime('%Y_%m')}.yml"
57
+ dbfile_basename_p = Pathname.new(dbfile_basename_s)
58
+ dbfile_path = dbfile_basename_p.expand_path(@data_path)
59
+ tmpfile_path = Pathname.new("#{dbfile_path}.tmp")
65
60
  file = {
66
61
  'meta' => {
67
62
  'version' => 1,
@@ -73,24 +68,19 @@ module TheFox
73
68
 
74
69
  @entries_index << entry.id
75
70
 
76
- # puts 'dbfile_basename: ' + dbfile_basename
77
- # puts 'dbfile_path: ' + dbfile_path
78
- # puts 'tmpfile_path: ' + tmpfile_path
79
- # puts
80
-
81
71
  if @has_transaction
82
- if @transaction_files.has_key?(dbfile_basename)
83
- file = @transaction_files[dbfile_basename]['file']
72
+ if @transaction_files[dbfile_basename_s]
73
+ file = @transaction_files[dbfile_basename_s]['file']
84
74
  else
85
- if File.exist?(dbfile_path)
75
+ if dbfile_path.exist?
86
76
  file = YAML.load_file(dbfile_path)
87
77
  file['meta']['updated_at'] = DateTime.now.to_s
88
78
  end
89
79
 
90
- @transaction_files[dbfile_basename] = {
91
- 'basename' => dbfile_basename,
92
- 'path' => dbfile_path,
93
- 'tmp_path' => tmpfile_path,
80
+ @transaction_files[dbfile_basename_s] = {
81
+ 'basename' => dbfile_basename_s,
82
+ 'path' => dbfile_path.to_s,
83
+ 'tmp_path' => tmpfile_path.to_s,
94
84
  'file' => file,
95
85
  }
96
86
  end
@@ -104,11 +94,9 @@ module TheFox
104
94
 
105
95
  file['days'][date_s].push(entry.to_h)
106
96
 
107
- @transaction_files[dbfile_basename]['file'] = file
97
+ @transaction_files[dbfile_basename_s]['file'] = file
108
98
  else
109
- create_dirs
110
-
111
- if File.exist?(dbfile_path)
99
+ if dbfile_path.exist?
112
100
  file = YAML.load_file(dbfile_path)
113
101
  file['meta']['updated_at'] = DateTime.now.to_s
114
102
  end
@@ -130,8 +118,8 @@ module TheFox
130
118
 
131
119
  save_entries_index_file
132
120
 
133
- if File.exist?(tmpfile_path)
134
- File.rename(tmpfile_path, dbfile_path)
121
+ if tmpfile_path.exist?
122
+ tmpfile_path.rename(dbfile_path)
135
123
  end
136
124
  end
137
125
 
@@ -157,12 +145,6 @@ module TheFox
157
145
  throw :done
158
146
  end
159
147
 
160
- # puts 'keys left: ' + @transaction_files.keys.count.to_s
161
- # puts 'tr_file_key: ' + tr_file_key
162
- # puts 'path: ' + tr_file_data['path']
163
- # puts 'tmp_path: ' + tr_file_data['tmp_path']
164
- # puts
165
-
166
148
  store = YAML::Store.new(tr_file_data['tmp_path'])
167
149
  store.transaction do
168
150
  store['meta'] = tr_file_data['file']['meta']
@@ -259,16 +241,8 @@ module TheFox
259
241
 
260
242
  category = category.to_s.downcase
261
243
 
262
- # puts 'glob: ' + glob
263
- # puts 'begin_year: ' + '%-10s' % begin_year.class.to_s + ' = "' + begin_year.to_s + '"'
264
- # puts 'begin_month: ' + '%-10s' % begin_month.class.to_s + ' = "' + begin_month.to_s + '"'
265
- # puts 'begin_day: ' + '%-10s' % begin_day.class.to_s + ' = "' + begin_day.to_s + '"'
266
- # puts 'category: ' + '%-10s' % category.class.to_s + ' = "' + category.to_s + '"'
267
- # puts
268
-
269
244
  entries_a = Hash.new
270
245
  Dir[glob].each do |file_path|
271
- #puts "path: #{file_path}"
272
246
 
273
247
  data = YAML.load_file(file_path)
274
248
  if category.length == 0
@@ -306,7 +280,7 @@ module TheFox
306
280
 
307
281
  def categories
308
282
  categories_h = Hash.new
309
- Dir[File.expand_path('month_*.yml', @data_path)].each do |file_path|
283
+ Dir[Pathname.new('month_*.yml').expand_path(@data_path)].each do |file_path|
310
284
  data = YAML.load_file(file_path)
311
285
 
312
286
  data['days'].each do |day_name, day_items|
@@ -328,10 +302,14 @@ module TheFox
328
302
  categories_a
329
303
  end
330
304
 
331
- def gen_html
305
+ def gen_html(html_path, date_start = nil, date_end = nil, category = nil)
332
306
  create_dirs
333
307
 
334
- html_options_path = File.expand_path('options.yml', @html_path)
308
+ unless html_path.exist?
309
+ html_path.mkpath
310
+ end
311
+
312
+ html_options_path = Pathname.new('options.yml').expand_path(html_path)
335
313
  html_options = {
336
314
  'meta' => {
337
315
  'version' => 1,
@@ -340,25 +318,30 @@ module TheFox
340
318
  },
341
319
  'changes' => Hash.new,
342
320
  }
343
- if Dir.exist?(@html_path)
344
- if File.exist?(html_options_path)
321
+ if html_path.exist?
322
+ if html_options_path.exist?
345
323
  html_options = YAML.load_file(html_options_path)
346
324
  html_options['meta']['updated_at'] = DateTime.now.to_s
347
325
  end
348
326
  else
349
- Dir.mkdir(@html_path)
327
+ html_path.mkpath
350
328
  end
351
329
 
352
330
  categories_available = categories
331
+ if category
332
+ filter_categories = category.split(',')
333
+ categories_available &= filter_categories
334
+ end
353
335
 
354
336
  categories_total_balance = Hash.new
355
337
  categories_available.map{ |item| categories_total_balance[item] = 0.0 }
356
338
 
357
- gitignore_file = File.open(File.expand_path('.gitignore', @html_path), 'w')
339
+ gitignore_file_path = Pathname.new('.gitignore').expand_path(html_path)
340
+ gitignore_file = File.open(gitignore_file_path, 'w')
358
341
  gitignore_file.write('*')
359
342
  gitignore_file.close
360
343
 
361
- css_file_path = File.expand_path('style.css', @html_path)
344
+ css_file_path = Pathname.new('style.css').expand_path(html_path)
362
345
  css_file = File.open(css_file_path, 'w')
363
346
  css_file.write('
364
347
  html {
@@ -383,37 +366,38 @@ module TheFox
383
366
  ')
384
367
  css_file.close
385
368
 
386
- index_file_path = File.expand_path('index.html', @html_path)
369
+ index_file_path = Pathname.new('index.html').expand_path(html_path)
387
370
  index_file = File.open(index_file_path, 'w')
388
371
  index_file.write('
389
372
  <html>
390
373
  <head>
391
374
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
392
- <title>' << @dir_path << '</title>
375
+ <title>' << @dir_path_basename_s << '</title>
393
376
  <link rel="stylesheet" href="style.css" type="text/css" />
394
377
  </head>
395
378
  <body>
396
- <h1>' << @dir_path << '</h1>
397
- <p>Generated @ ' << DateTime.now.strftime('%Y-%m-%d %H:%M:%S') << ' by <a href="' << ::TheFox::Wallet::HOMEPAGE << '">' << ::TheFox::Wallet::NAME << '</a> ' << ::TheFox::Wallet::VERSION << '</p>
379
+ <h1>' << @dir_path_basename_s << '</h1>
380
+ <p>Generated @ ' << DateTime.now.strftime('%F %T') << ' by <a href="' << HOMEPAGE << '">' << NAME << '</a> v' << VERSION << '</p>
398
381
  ')
399
382
 
400
383
  years_total = Hash.new
401
- years.each do |year|
384
+ years(date_start, date_end).each do |year|
402
385
  year_s = year.to_s
403
- year_file_name = "year_#{year}.html"
404
- year_file_path = File.expand_path(year_file_name, @html_path)
386
+ year_file_name_s = "year_#{year}.html"
387
+ year_file_name_p = Pathname.new(year_file_name_s)
388
+ year_file_path = year_file_name_p.expand_path(html_path)
405
389
 
406
390
  year_file = File.open(year_file_path, 'w')
407
391
  year_file.write('
408
392
  <html>
409
393
  <head>
410
394
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
411
- <title>' << year_s << ' - ' << @dir_path << '</title>
395
+ <title>' << year_s << ' - ' << @dir_path_basename_s << '</title>
412
396
  <link rel="stylesheet" href="style.css" type="text/css" />
413
397
  </head>
414
398
  <body>
415
- <h1><a href="index.html">' << @dir_path << '</a></h1>
416
- <p>Generated @ ' << DateTime.now.strftime('%Y-%m-%d %H:%M:%S') << ' by <a href="' << ::TheFox::Wallet::HOMEPAGE << '">' << ::TheFox::Wallet::NAME << '</a> ' << ::TheFox::Wallet::VERSION << '</p>
399
+ <h1><a href="index.html">' << @dir_path_basename_s << '</a></h1>
400
+ <p>Generated @ ' << DateTime.now.strftime('%Y-%m-%d %H:%M:%S') << ' by <a href="' << HOMEPAGE << '">' << NAME << '</a> v' << VERSION << '</p>
417
401
 
418
402
  <h2>Year: ' << year_s << '</h2>
419
403
  <table class="list">
@@ -428,7 +412,7 @@ module TheFox
428
412
  <th colspan="4">&nbsp;</th>
429
413
  ')
430
414
  categories_available.each do |category|
431
- year_file.write('<th class="right">' << category << '</th>')
415
+ year_file.write(%(<th class="right">#{category}</th>))
432
416
  end
433
417
  year_file.write('</tr>')
434
418
 
@@ -439,15 +423,32 @@ module TheFox
439
423
  categories_available.map{ |item| categories_year_balance[item] = 0.0 }
440
424
  year_total = Hash.new
441
425
 
442
- puts "generate year #{year}"
443
- Dir[File.expand_path("month_#{year}_*.yml", @data_path)].each do |file_path|
444
- file_name = File.basename(file_path)
445
- month_n = file_name[11, 2]
446
- month_file_name = "month_#{year}_#{month_n}.html"
447
- month_file_path = File.expand_path(month_file_name, @html_path)
426
+ @logger.info("generate year #{year}") if @logger
427
+ @data_path.each_child do |file_path|
428
+ file_name_p = file_path.basename
429
+ file_name_s = file_name_p.to_s
430
+
431
+ if file_path.extname != '.yml' || Regexp.new("^month_#{year}_").match(file_name_s).nil?
432
+ next
433
+ end
434
+
435
+ month_n = file_name_s[11, 2]
436
+ month_file_name_s = "month_#{year}_#{month_n}.html"
437
+ month_file_name_p = Pathname.new(month_file_name_s)
438
+ month_file_path = month_file_name_p.expand_path(html_path)
448
439
 
449
440
  month_s = Date.parse("2015-#{month_n}-15").strftime('%B')
450
441
 
442
+ if date_start && date_end
443
+ file_date_start = Date.parse("#{year}-#{month_n}-01")
444
+ file_date_end = Date.parse("#{year}-#{month_n}-01").next_month.prev_day
445
+
446
+ if date_end < file_date_start ||
447
+ date_start > file_date_end
448
+ next
449
+ end
450
+ end
451
+
451
452
  revenue_month = 0.0
452
453
  expense_month = 0.0
453
454
  balance_month = 0.0
@@ -458,37 +459,37 @@ module TheFox
458
459
  data = YAML.load_file(file_path)
459
460
 
460
461
  generate_html = false
461
- if html_options['changes'].has_key?(file_name)
462
- if html_options['changes'][file_name]['updated_at'] != data['meta']['updated_at']
463
- html_options['changes'][file_name]['updated_at'] = data['meta']['updated_at']
462
+ if html_options['changes'][file_name_s]
463
+ if html_options['changes'][file_name_s]['updated_at'] != data['meta']['updated_at']
464
+ html_options['changes'][file_name_s]['updated_at'] = data['meta']['updated_at']
464
465
  generate_html = true
465
466
  end
466
467
  else
467
- html_options['changes'][file_name] = {
468
+ html_options['changes'][file_name_s] = {
468
469
  'updated_at' => data['meta']['updated_at'],
469
470
  }
470
471
  generate_html = true
471
472
  end
472
- if !File.exist?(month_file_path)
473
+ unless month_file_path.exist?
473
474
  generate_html = true
474
475
  end
475
476
 
476
477
  if generate_html
477
- puts "\tfile: #{month_file_name} (from #{file_name})"
478
+ @logger.debug("file: #{month_file_name_s} (from #{file_name_s})") if @logger
478
479
 
479
480
  month_file = File.open(month_file_path, 'w')
480
481
  month_file.write('
481
482
  <html>
482
483
  <head>
483
484
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
484
- <title>' << month_s << ' ' << year_s << ' - ' << @dir_path << '</title>
485
+ <title>' << month_s << ' ' << year_s << ' - ' << @dir_path_basename_s << '</title>
485
486
  <link rel="stylesheet" href="style.css" type="text/css" />
486
487
  </head>
487
488
  <body>
488
- <h1><a href="index.html">' << @dir_path << '</a></h1>
489
- <p>Generated @ ' << DateTime.now.strftime('%Y-%m-%d %H:%M:%S') << ' by <a href="' << ::TheFox::Wallet::HOMEPAGE << '">' << ::TheFox::Wallet::NAME << '</a> ' << ::TheFox::Wallet::VERSION << ' from <code>' << file_name << '</code></p>
489
+ <h1><a href="index.html">' << @dir_path_basename_s << '</a></h1>
490
+ <p>Generated @ ' << DateTime.now.strftime('%Y-%m-%d %H:%M:%S') << ' by <a href="' << HOMEPAGE << '">' << NAME << '</a> v' << VERSION << ' from <code>' << file_name_s << '</code></p>
490
491
 
491
- <h2>Month: ' << month_s << ' <a href="' << year_file_name << '">' << year_s << '</a></h2>
492
+ <h2>Month: ' << month_s << ' <a href="' << year_file_name_s << '">' << year_s << '</a></h2>
492
493
  <table class="list">
493
494
  <tr>
494
495
  <th class="left">#</th>
@@ -505,6 +506,19 @@ module TheFox
505
506
 
506
507
  data['days'].sort.each do |day_name, day_items|
507
508
  day_items.each do |entry|
509
+ entry_date = Date.parse(entry['date'])
510
+ entry_date_s = entry_date.strftime('%d.%m.%y')
511
+
512
+ date_start_oor = date_start > entry_date
513
+ date_end_oor = date_end < entry_date
514
+
515
+ if category && !categories_available.include?(entry['category']) ||
516
+ date_start > entry_date ||
517
+ date_end < entry_date
518
+
519
+ next
520
+ end
521
+
508
522
  entry_n += 1
509
523
  revenue_month += entry['revenue']
510
524
  expense_month += entry['expense']
@@ -513,8 +527,8 @@ module TheFox
513
527
  categories_year_balance[entry['category']] += entry['balance']
514
528
  categories_month_balance[entry['category']] += entry['balance']
515
529
 
516
- revenue_out = entry['revenue'] > 0 ? ::TheFox::Wallet::NUMBER_FORMAT % entry['revenue'] : '&nbsp;'
517
- expense_out = entry['expense'] < 0 ? ::TheFox::Wallet::NUMBER_FORMAT % entry['expense'] : '&nbsp;'
530
+ revenue_out = entry['revenue'] > 0 ? NUMBER_FORMAT % entry['revenue'] : '&nbsp;'
531
+ expense_out = entry['expense'] < 0 ? NUMBER_FORMAT % entry['expense'] : '&nbsp;'
518
532
  category_out = entry['category'] == 'default' ? '&nbsp;' : entry['category']
519
533
  comment_out = entry['comment'] == '' ? '&nbsp;' : entry['comment']
520
534
 
@@ -522,11 +536,11 @@ module TheFox
522
536
  month_file.write('
523
537
  <tr>
524
538
  <td valign="top" class="left">' << entry_n.to_s << '</td>
525
- <td valign="top" class="left">' << Date.parse(entry['date']).strftime('%d.%m.%y') << '</td>
539
+ <td valign="top" class="left">' << entry_date_s << '</td>
526
540
  <td valign="top" class="left">' << entry['title'][0, 50] << '</td>
527
541
  <td valign="top" class="right">' << revenue_out << '</td>
528
542
  <td valign="top" class="right red">' << expense_out << '</td>
529
- <td valign="top" class="right ' << (entry['balance'] < 0 ? 'red' : '') << '">' << ::TheFox::Wallet::NUMBER_FORMAT % entry['balance'] << '</td>
543
+ <td valign="top" class="right ' << (entry['balance'] < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % entry['balance'] << '</td>
530
544
  <td valign="top" class="right">' << category_out << '</td>
531
545
  <td valign="top" class="left">' << comment_out << '</td>
532
546
  </tr>
@@ -561,9 +575,9 @@ module TheFox
561
575
  <th>&nbsp;</th>
562
576
  <th>&nbsp;</th>
563
577
  <th class="left"><b>TOTAL</b></th>
564
- <th class="right">' << ::TheFox::Wallet::NUMBER_FORMAT % revenue_month << '</th>
565
- <th class="right red">' << ::TheFox::Wallet::NUMBER_FORMAT % expense_month << '</th>
566
- <th class="right ' << balance_class << '">' << ::TheFox::Wallet::NUMBER_FORMAT % balance_month << '</th>
578
+ <th class="right">' << NUMBER_FORMAT % revenue_month << '</th>
579
+ <th class="right red">' << NUMBER_FORMAT % expense_month << '</th>
580
+ <th class="right ' << balance_class << '">' << NUMBER_FORMAT % balance_month << '</th>
567
581
  <th>&nbsp;</th>
568
582
  <th>&nbsp;</th>
569
583
  </tr>
@@ -574,13 +588,13 @@ module TheFox
574
588
 
575
589
  year_file.write('
576
590
  <tr>
577
- <td class="left"><a href="' << month_file_name << '">' << month_s << '</a></td>
578
- <td class="right">' << ::TheFox::Wallet::NUMBER_FORMAT % revenue_month << '</td>
579
- <td class="right red">' << ::TheFox::Wallet::NUMBER_FORMAT % expense_month << '</td>
580
- <td class="right ' << balance_class << '">' << ::TheFox::Wallet::NUMBER_FORMAT % balance_month << '</td>')
591
+ <td class="left"><a href="' << month_file_name_s << '">' << month_s << '</a></td>
592
+ <td class="right">' << NUMBER_FORMAT % revenue_month << '</td>
593
+ <td class="right red">' << NUMBER_FORMAT % expense_month << '</td>
594
+ <td class="right ' << balance_class << '">' << NUMBER_FORMAT % balance_month << '</td>')
581
595
  categories_available.each do |category|
582
596
  category_balance = categories_month_balance[category]
583
- year_file.write('<td class="right ' << (category_balance < 0 ? 'red' : '') << '">' << ::TheFox::Wallet::NUMBER_FORMAT % category_balance << '</td>')
597
+ year_file.write('<td class="right ' << (category_balance < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % category_balance << '</td>')
584
598
  end
585
599
  year_file.write('</tr>')
586
600
  end
@@ -590,12 +604,12 @@ module TheFox
590
604
  year_file.write('
591
605
  <tr>
592
606
  <th class="left"><b>TOTAL</b></th>
593
- <th class="right">' << ::TheFox::Wallet::NUMBER_FORMAT % revenue_year << '</th>
594
- <th class="right red">' << ::TheFox::Wallet::NUMBER_FORMAT % expense_year << '</th>
595
- <th class="right ' << (balance_year < 0 ? 'red' : '') << '">' << ::TheFox::Wallet::NUMBER_FORMAT % balance_year << '</th>')
607
+ <th class="right">' << NUMBER_FORMAT % revenue_year << '</th>
608
+ <th class="right red">' << NUMBER_FORMAT % expense_year << '</th>
609
+ <th class="right ' << (balance_year < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % balance_year << '</th>')
596
610
  categories_available.each do |category|
597
611
  category_balance = categories_year_balance[category]
598
- year_file.write('<td class="right ' << (category_balance < 0 ? 'red' : '') << '">' << ::TheFox::Wallet::NUMBER_FORMAT % category_balance << '</td>')
612
+ year_file.write('<td class="right ' << (category_balance < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % category_balance << '</td>')
599
613
  end
600
614
 
601
615
  year_file.write('
@@ -607,42 +621,15 @@ module TheFox
607
621
  year_file.write('</body></html>')
608
622
  year_file.close
609
623
 
610
- yeardat_file_path = File.expand_path("year_#{year_s}.dat", @tmp_path)
624
+ yeardat_file_path = Pathname.new("year_#{year_s}.dat").expand_path(@tmp_path)
611
625
  yeardat_file = File.new(yeardat_file_path, 'w')
612
626
  yeardat_file.write(year_total
613
627
  .map{ |k, m| "#{year_s}-#{m.month_s} #{m.revenue} #{m.expense} #{m.balance} #{m.balance_total} #{m.balance_total}" }
614
628
  .join("\n"))
615
629
  yeardat_file.close
616
630
 
617
- # year_max = year_total
618
- # .map{ |k, m| [m.revenue, m.balance, m.balance_total] }
619
- # .flatten
620
- # .max
621
- # .to_i
622
-
623
- # year_min = year_total
624
- # .map{ |k, m| [m.expense, m.balance, m.balance_total] }
625
- # .flatten
626
- # .min
627
- # .to_i
628
- # .abs
629
-
630
- # year_max_rl = year_max.to_s.length - 2
631
- # year_max_r = year_max.round(-year_max_rl)
632
- # year_max_d = year_max_r - year_max
633
- # year_max_r = year_max_r + 5 * 10 ** (year_max_rl - 1) if year_max_r < year_max
634
- # year_max_r += 100
635
-
636
- # year_min_rl = year_min.to_s.length - 2
637
- # year_min_r = year_min.round(-year_min_rl)
638
- # year_min_d = year_min_r - year_min
639
- # year_min_r = year_min_r + 5 * 10 ** (year_min_rl - 1) if year_min_r < year_min
640
- # year_min_r += 100
641
-
642
- # puts "#{year_max} #{year_max.to_s.length} #{year_max_r} #{year_max_rl}"
643
- # puts "#{year_min} #{year_min.to_s.length} #{year_min_r} #{year_min_rl}"
644
-
645
- gnuplot_file = File.new(File.expand_path("year_#{year_s}.gp", @tmp_path), 'w')
631
+ gnuplot_file_path = Pathname.new("year_#{year_s}.gp").expand_path(@tmp_path)
632
+ gnuplot_file = File.new(gnuplot_file_path, 'w')
646
633
  gnuplot_file.puts("set title 'Year #{year_s}'")
647
634
  gnuplot_file.puts("set xlabel 'Months'")
648
635
  gnuplot_file.puts("set ylabel 'Euro'")
@@ -665,14 +652,14 @@ module TheFox
665
652
  gnuplot_file.puts("set style line 4 linecolor rgb '#0000ff' linewidth 2 linetype 1 pointtype 2")
666
653
  gnuplot_file.puts("set style data linespoints")
667
654
  gnuplot_file.puts("set terminal png enhanced")
668
- gnuplot_file.puts("set output '" << File.expand_path("year_#{year_s}.png", @html_path) << "'")
655
+ gnuplot_file.puts("set output '" << File.expand_path("year_#{year_s}.png", html_path) << "'")
669
656
  gnuplot_file.puts("plot sum = 0, \\")
670
657
  gnuplot_file.puts("\t'#{yeardat_file_path}' using 1:2 linestyle 1 title 'Revenue', \\")
671
658
  gnuplot_file.puts("\t'' using 1:3 linestyle 2 title 'Expense', \\")
672
659
  gnuplot_file.puts("\t'' using 1:4 linestyle 3 title 'Balance', \\")
673
660
  gnuplot_file.puts("\t'' using 1:5 linestyle 4 title '∑ Balance'")
674
661
  gnuplot_file.close
675
- system("gnuplot " << File.expand_path("year_#{year_s}.gp", @tmp_path))
662
+ system("gnuplot #{gnuplot_file_path} &> /dev/null")
676
663
 
677
664
  years_total[year_s] = ::OpenStruct.new({
678
665
  year: year_s,
@@ -697,10 +684,10 @@ module TheFox
697
684
  index_file.write('
698
685
  <tr>
699
686
  <td class="left"><a href="year_' << year_name << '.html">' << year_name << '</a></td>
700
- <td class="right">' << ::TheFox::Wallet::NUMBER_FORMAT % year_data.revenue << '</td>
701
- <td class="right red">' << ::TheFox::Wallet::NUMBER_FORMAT % year_data.expense << '</td>
702
- <td class="right ' << (year_data.balance < 0 ? 'red' : '') << '">' << ::TheFox::Wallet::NUMBER_FORMAT % year_data.balance << '</td>
703
- <td class="right ' << (year_data.balance_total < 0 ? 'red' : '') << '">' << ::TheFox::Wallet::NUMBER_FORMAT % year_data.balance_total << '</td>
687
+ <td class="right">' << NUMBER_FORMAT % year_data.revenue << '</td>
688
+ <td class="right red">' << NUMBER_FORMAT % year_data.expense << '</td>
689
+ <td class="right ' << (year_data.balance < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % year_data.balance << '</td>
690
+ <td class="right ' << (year_data.balance_total < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % year_data.balance_total << '</td>
704
691
  </tr>')
705
692
  end
706
693
 
@@ -709,9 +696,9 @@ module TheFox
709
696
  index_file.write('
710
697
  <tr>
711
698
  <th class="left"><b>TOTAL</b></th>
712
- <th class="right">' << ::TheFox::Wallet::NUMBER_FORMAT % years_total.inject(0.0){ |sum, item| sum + item[1].revenue } << '</th>
713
- <th class="right red">' << ::TheFox::Wallet::NUMBER_FORMAT % years_total.inject(0.0){ |sum, item| sum + item[1].expense } << '</th>
714
- <th class="right ' << (balance_total < 0 ? 'red' : '') << '">' << ::TheFox::Wallet::NUMBER_FORMAT % balance_total << '</th>
699
+ <th class="right">' << NUMBER_FORMAT % years_total.inject(0.0){ |sum, item| sum + item[1].revenue } << '</th>
700
+ <th class="right red">' << NUMBER_FORMAT % years_total.inject(0.0){ |sum, item| sum + item[1].expense } << '</th>
701
+ <th class="right ' << (balance_total < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % balance_total << '</th>
715
702
  <th>&nbsp;</th>
716
703
  </tr>
717
704
  </table>
@@ -731,17 +718,20 @@ module TheFox
731
718
  end
732
719
 
733
720
  totaldat_file_c = years_total.map{ |k, y| "#{y.year} #{y.revenue} #{y.expense} #{y.balance} #{y.balance_total}" }
734
- if totaldat_file_c.count > 6
735
- totaldat_file_c = totaldat_file_c.slice(-6, 6)
721
+ if totaldat_file_c.count > 10
722
+ totaldat_file_c = totaldat_file_c.slice(-10, 10)
736
723
  end
737
724
  totaldat_file_c = totaldat_file_c.join("\n")
738
725
 
739
- totaldat_file_path = File.expand_path('total.dat', @tmp_path)
726
+ totaldat_file_path = Pathname.new('total.dat').expand_path(@tmp_path)
740
727
  totaldat_file = File.new(totaldat_file_path, 'w')
741
728
  totaldat_file.write(totaldat_file_c)
742
729
  totaldat_file.close
743
730
 
744
- gnuplot_file = File.new(File.expand_path('total.gp', @tmp_path), 'w')
731
+ png_file_path = Pathname.new('total.png').expand_path(html_path)
732
+
733
+ gnuplot_file_path = Pathname.new('total.gp').expand_path(@tmp_path)
734
+ gnuplot_file = File.new(gnuplot_file_path, 'w')
745
735
  gnuplot_file.puts("set title 'Total'")
746
736
  gnuplot_file.puts("set xlabel 'Years'")
747
737
  gnuplot_file.puts("set ylabel 'Euro'")
@@ -756,7 +746,7 @@ module TheFox
756
746
  gnuplot_file.puts("set style line 4 linecolor rgb '#0000ff' linewidth 2 linetype 1 pointtype 2")
757
747
  gnuplot_file.puts("set style data linespoints")
758
748
  gnuplot_file.puts("set terminal png enhanced")
759
- gnuplot_file.puts("set output '" << File.expand_path('total.png', @html_path) << "'")
749
+ gnuplot_file.puts("set output '#{png_file_path}'")
760
750
  gnuplot_file.puts("plot sum = 0, \\")
761
751
  gnuplot_file.puts("\t'#{totaldat_file_path}' using 1:2 linestyle 1 title 'Revenue', \\")
762
752
  gnuplot_file.puts("\t'' using 1:3 linestyle 2 title 'Expense', \\")
@@ -764,7 +754,7 @@ module TheFox
764
754
  gnuplot_file.puts("\t'' using 1:5 linestyle 4 title '∑ Balance'")
765
755
  gnuplot_file.close
766
756
 
767
- system("gnuplot " << File.expand_path('total.gp', @tmp_path))
757
+ system("gnuplot #{gnuplot_file_path} &> /dev/null")
768
758
  end
769
759
 
770
760
  def import_csv_file(file_path)
@@ -796,11 +786,10 @@ module TheFox
796
786
 
797
787
  added = add(Entry.new(id, title, date, revenue, expense, category, comment), true)
798
788
 
799
- puts "import row '#{id}' -- #{added ? 'YES' : 'NO'}"
789
+ @logger.debug("import row '#{id}' -- #{added ? 'YES' : 'NO'}") if @logger
800
790
  end
801
791
 
802
- puts
803
- puts 'save data ...'
792
+ @logger.info('save data ...') if @logger
804
793
 
805
794
  transaction_end
806
795
  end
@@ -816,8 +805,8 @@ module TheFox
816
805
  # :encoding => 'ISO-8859-1',
817
806
  }
818
807
  CSV.open(file_path, 'wb', csv_options) do |csv|
819
- Dir[File.expand_path('month_*.yml', @data_path)].each do |yaml_file_path|
820
- puts 'export ' + File.basename(yaml_file_path)
808
+ Dir[Pathname.new('month_*.yml').expand_path(@data_path)].each do |yaml_file_path|
809
+ @logger.info("export #{File.basename(yaml_file_path)}") if @logger
821
810
 
822
811
  data = YAML.load_file(yaml_file_path)
823
812
 
@@ -827,9 +816,9 @@ module TheFox
827
816
  entry['id'],
828
817
  entry['date'],
829
818
  entry['title'],
830
- ::TheFox::Wallet::NUMBER_FORMAT % entry['revenue'],
831
- ::TheFox::Wallet::NUMBER_FORMAT % entry['expense'],
832
- ::TheFox::Wallet::NUMBER_FORMAT % entry['balance'],
819
+ NUMBER_FORMAT % entry['revenue'],
820
+ NUMBER_FORMAT % entry['expense'],
821
+ NUMBER_FORMAT % entry['balance'],
833
822
  entry['category'],
834
823
  entry['comment'],
835
824
  ]
@@ -854,9 +843,9 @@ module TheFox
854
843
  if @entries_by_ids.nil? || force
855
844
  @logger.debug('build entry-by-id index') if @logger
856
845
 
857
- glob = File.expand_path('month_*.yml', @data_path)
846
+ glob = Pathname.new('month_*.yml').expand_path(@data_path)
858
847
 
859
- @entries_by_ids = Dir[glob].map { |file_path|
848
+ @entries_by_ids = Dir[glob.to_s].map { |file_path|
860
849
  data = YAML.load_file(file_path)
861
850
  data['days'].map{ |day_name, day_items|
862
851
  day_items.map{ |entry|
@@ -866,8 +855,6 @@ module TheFox
866
855
  }.flatten.map{ |entry|
867
856
  [entry.id, entry]
868
857
  }.to_h
869
-
870
- # pp @entries_by_ids
871
858
  end
872
859
  end
873
860
 
@@ -880,26 +867,26 @@ module TheFox
880
867
  private
881
868
 
882
869
  def create_dirs
883
- if !Dir.exist?(@dir_path)
884
- Dir.mkdir(@dir_path)
870
+ unless @dir_path.exist?
871
+ @dir_path.mkpath
885
872
  end
886
873
 
887
- if !Dir.exist?(@data_path)
888
- Dir.mkdir(@data_path)
874
+ unless @data_path.exist?
875
+ @data_path.mkpath
889
876
  end
890
877
 
891
- if !Dir.exist?(@tmp_path)
892
- Dir.mkdir(@tmp_path)
878
+ unless @tmp_path.exist?
879
+ @tmp_path.mkpath
893
880
  end
894
881
 
895
- tmp_gitignore_path = File.expand_path('.gitignore', @tmp_path)
896
- if !File.exist?(tmp_gitignore_path)
882
+ tmp_gitignore_path = Pathname.new('.gitignore').expand_path(@tmp_path)
883
+ unless tmp_gitignore_path.exist?
897
884
  gitignore_file = File.open(tmp_gitignore_path, 'w')
898
885
  gitignore_file.write('*')
899
886
  gitignore_file.close
900
887
  end
901
888
 
902
- if File.exist?(@entries_index_file_path)
889
+ if @entries_index_file_path.exist?
903
890
  load_entries_index_file
904
891
  else
905
892
  build_entry_by_id_index(true)
@@ -937,22 +924,39 @@ module TheFox
937
924
  }
938
925
  end
939
926
 
940
- def years
941
- Dir[File.expand_path('month_*.yml', @data_path)].map{ |file_path| File.basename(file_path)[6, 4].to_i }.uniq
927
+ def years(date_start = nil, date_end = nil)
928
+
929
+ files = Array.new
930
+ @data_path.each_child(false) do |file|
931
+ if file.extname == '.yml' && /^month_/.match(file.to_s)
932
+ files << file
933
+ end
934
+ end
935
+
936
+ date_start_year = 0
937
+ date_start_year = date_start.year if date_start
938
+
939
+ date_end_year = 9999
940
+ date_end_year = date_end.year if date_end
941
+
942
+ files
943
+ .map{ |file| file.to_s[6, 4].to_i }
944
+ .uniq
945
+ .keep_if{ |year| year >= date_start_year && year <= date_end_year }
942
946
  end
943
947
 
944
948
  def load_entries_index_file
945
949
  unless @entries_index_is_loaded
946
950
  @entries_index_is_loaded = true
947
- if File.exist?(@entries_index_file_path)
948
- data = YAML.load_file(@entries_index_file_path)
951
+ if @entries_index_file_path.exist?
952
+ data = YAML.load_file(@entries_index_file_path.to_s)
949
953
  @entries_index = data['index']
950
954
  end
951
955
  end
952
956
  end
953
957
 
954
958
  def save_entries_index_file
955
- store = YAML::Store.new(@entries_index_file_path)
959
+ store = YAML::Store.new(@entries_index_file_path.to_s)
956
960
  store.transaction do
957
961
  store['index'] = @entries_index
958
962
  end