thefox-wallet 0.18.0 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fffbb8179bacdf2090fea639b32169a971c74cc41a3aa9a6b4cd618232a42ea
4
- data.tar.gz: e67c28cb3d33b3836fc0f1a3ff9340ef97203bb41c9fdd73dd81eb18f568b9fe
3
+ metadata.gz: dbdeab5e10aa901509aad542748c877b974843a7acab66c0666fffc831b9d40e
4
+ data.tar.gz: 05e48b852ff486781c50cc205b36a4ed4143d3c3f9f10f706168d999288e0d93
5
5
  SHA512:
6
- metadata.gz: da2e9b2af441f797323b91d8904a31e357080a0b367e80479b94c3ce9680af9a999a00e4d77c04d9147e4f532ba14f9bd65e582942bf420c3b14cf075437e860
7
- data.tar.gz: dd07b9c48990f1e207ee8225c86dad436e62467d109e507bf7de3fc741f0f510afad97ca4540d173a560921bedb27f322616c224d011e93dd8b5a9f6d3e40780
6
+ metadata.gz: 993f8b9b4404d12029eaa61917ab6de5a42996fc70d2c8a5a0545a557e5ce5a0e141f51a1741f49d556ffb676ea4159411bb4db57b36aae7e1418bea16a70a83
7
+ data.tar.gz: 8f27dc5b78ff979d69d1df2c4305d68b1628659fd93bf887c818180aa6ec4f9eb9eeb233ce4596841221c7116de3e2dc4f1f35044d4395fc7cab73af91490403
data/.editorconfig CHANGED
@@ -10,6 +10,6 @@ charset = utf-8
10
10
  trim_trailing_whitespace = false
11
11
  insert_final_newline = true
12
12
 
13
- [*.{sh}]
13
+ [*.{sh,css}]
14
14
  indent_style = tab
15
15
  indent_size = 4
data/.gitlab-ci.yml CHANGED
@@ -9,15 +9,6 @@ stages:
9
9
  - test
10
10
  - release
11
11
 
12
- test_21:
13
- image: ruby:2.1
14
- stage: test
15
- environment: test
16
- only:
17
- - tags
18
- script:
19
- - ./bin/test.sh
20
-
21
12
  test_22:
22
13
  image: ruby:2.2
23
14
  stage: test
data/.travis.yml CHANGED
@@ -1,6 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1
4
3
  - 2.2
5
4
  - 2.3
6
5
  - 2.4.0
data/README.md CHANGED
@@ -27,7 +27,7 @@ $ gem install thefox-wallet
27
27
  or via `Gemfile`:
28
28
 
29
29
  ```sh
30
- $ gem 'thefox-wallet', '~>0.18'
30
+ $ gem 'thefox-wallet', '~>0.19'
31
31
  ```
32
32
 
33
33
  Use it in your sources:
data/Vagrantfile CHANGED
@@ -1,28 +1,32 @@
1
1
  # -*- mode: ruby -*-
2
2
  # vi: set ft=ruby :
3
3
 
4
- Vagrant.configure("2") do |config|
5
- config.vm.box = "generic/debian9"
4
+ Vagrant.configure('2') do |config|
5
+ config.vm.box = 'generic/debian9'
6
6
  config.vm.box_check_update = false
7
7
 
8
- # config.vm.network "forwarded_port", guest: 4000, host: 4001
8
+ config.vm.hostname = 'wallet'
9
+ # config.vm.network 'forwarded_port', guest: 4000, host: 4001
9
10
 
10
- # config.vm.network "private_network", ip: "192.168.33.10"
11
- config.vm.synced_folder ".", "/app"
11
+ # config.vm.network 'private_network', ip: '192.168.33.10'
12
+ config.vm.synced_folder '.', '/app'
12
13
 
13
- config.vm.provider "virtualbox" do |vb|
14
+ config.vm.provider 'virtualbox' do |vb|
14
15
  vb.gui = false
15
16
  vb.memory = 1024
16
17
  end
17
18
 
18
- config.vm.provision "shell" do |s|
19
+ config.vm.provision 'shell' do |s|
19
20
  s.env = {
20
21
  'DEBIAN_FRONTEND' => 'noninteractive',
22
+ 'WORKING_DIR' => '/app',
21
23
  }
22
24
  s.inline = <<-SHELL
25
+ echo "cd ${WORKING_DIR}" >> /home/vagrant/.bashrc
26
+
23
27
  apt-get update -yqq
24
28
  apt-get upgrade -y
25
- apt-get install -y htop vim lsof net-tools rsync ruby ruby-dev
29
+ apt-get install -y htop vim lsof net-tools rsync ruby ruby-dev gnuplot
26
30
 
27
31
  gem update --system && \
28
32
  gem install bundler -v '1.15.4' && \
data/bin/.gitignore ADDED
@@ -0,0 +1 @@
1
+ test.rb
File without changes
data/bin/wallet CHANGED
@@ -36,6 +36,10 @@ opts = OptionParser.new do |o|
36
36
  @options[:entry_title] = title
37
37
  end
38
38
 
39
+ o.on('-m', '--message <message>', 'Alias for --title.') do |message|
40
+ @options[:entry_title] = message
41
+ end
42
+
39
43
  o.on('-d', '--date <YYYY-MM-DD>', 'Date used for a new entry.') do |date|
40
44
  @options[:entry_date] = date
41
45
  end
data/lib/wallet/entry.rb CHANGED
@@ -62,8 +62,8 @@ module TheFox
62
62
  when String
63
63
  # String
64
64
  @date = Date.parse(date)
65
- when Fixnum
66
- # Fixnum
65
+ when Integer
66
+ # Integer
67
67
  @date = Time.at(date).to_date
68
68
  when Date
69
69
  # Date
@@ -2,11 +2,12 @@
2
2
  module TheFox
3
3
  module Wallet
4
4
  NAME = 'Wallet'
5
- VERSION = '0.18.0'
6
- DATE = '2018-08-13'
5
+ VERSION = '0.19.0'
6
+ DATE = '2018-09-01'
7
7
  HOMEPAGE = 'https://github.com/TheFox/wallet'
8
8
 
9
9
  NUMBER_FORMAT = '%.2f'
10
10
  NUMBER_ROUND = 5
11
+ DATETIME_FORMAT = '%F %T %Z'
11
12
  end
12
13
  end
data/lib/wallet/wallet.rb CHANGED
@@ -7,6 +7,9 @@ require 'yaml/store'
7
7
  require 'csv'
8
8
  require 'pathname'
9
9
  require 'fileutils'
10
+ require 'rubygems'
11
+ require 'liquid'
12
+ require 'pp'
10
13
 
11
14
  # OpenStruct use to generate HTML.
12
15
  require 'ostruct'
@@ -39,6 +42,10 @@ module TheFox
39
42
  @entries_index = Array.new
40
43
  @entries_index_is_loaded = false
41
44
 
45
+ spec = Gem::Specification.find_by_name('thefox-wallet')
46
+ @gem_root = Pathname.new(spec.gem_dir)
47
+ @resources_root = Pathname.new('resources').expand_path(@gem_root)
48
+
42
49
  Signal.trap('SIGINT') do
43
50
  #@logger.warn('received SIGINT. break ...')
44
51
  @exit = true
@@ -340,7 +347,7 @@ module TheFox
340
347
 
341
348
  create_dirs
342
349
 
343
- unless html_path.exist?
350
+ if not html_path.exist?
344
351
  html_path.mkpath
345
352
  end
346
353
 
@@ -376,36 +383,29 @@ module TheFox
376
383
  gitignore_file = File.open(gitignore_file_path, 'w')
377
384
  gitignore_file.write('*')
378
385
  gitignore_file.close
379
-
386
+
380
387
  # Write CSS file.
381
- css_file_path = Pathname.new('style.css').expand_path(html_path)
382
- css_file = File.open(css_file_path, 'w')
383
- css_file.write('
384
- html {
385
- -webkit-text-size-adjust: none;
386
- }
387
- table.list, table.list th, table.list td {
388
- border: 1px solid black;
389
- }
390
- th.left, td.left {
391
- text-align: left;
392
- }
393
- th.right, td.right {
394
- text-align: right;
395
- }
396
- th.first_column {
397
- min-width: 180px;
398
- width: 180px;
399
- }
400
- th.red, td.red {
401
- color: #ff0000;
402
- }
403
- ')
404
- css_file.close
388
+ src_css_file_path = Pathname.new('css/style.css').expand_path(@resources_root).to_s
389
+ dst_css_file_path = Pathname.new('style.css').expand_path(html_path).to_s
390
+
391
+ # FileUtils.cp_r(src_css_file_path, dst_css_file_path, {:verbose => true})
392
+ %x[cp #{src_css_file_path} #{dst_css_file_path}];
405
393
 
406
394
  # Use this for index.html.
407
395
  years_total = Hash.new
408
396
 
397
+ # Year HTML Template
398
+ year_liquid_tpl_src = Pathname.new('views/year.liquid').expand_path(@resources_root).to_s
399
+ year_liquid_tpl = Liquid::Template.parse(File.read(year_liquid_tpl_src))
400
+
401
+ # Month HTML Template
402
+ month_liquid_tpl_src = Pathname.new('views/month.liquid').expand_path(@resources_root).to_s
403
+ month_liquid_tpl = Liquid::Template.parse(File.read(month_liquid_tpl_src))
404
+
405
+ # Gnuplot Template
406
+ gnuplot_year_liquid_tpl_src = Pathname.new('gnuplot/year_config.liquid').expand_path(@resources_root).to_s
407
+ gnuplot_year_liquid_tpl = Liquid::Template.parse(File.read(gnuplot_year_liquid_tpl_src))
408
+
409
409
  # Iterate over all years.
410
410
  years(date_start, date_end).each do |year|
411
411
  year_s = year.to_s
@@ -413,35 +413,6 @@ module TheFox
413
413
  year_file_name_p = Pathname.new(year_file_name_s)
414
414
  year_file_path = year_file_name_p.expand_path(html_path)
415
415
 
416
- year_file = File.open(year_file_path, 'w')
417
- year_file.write('
418
- <html>
419
- <head>
420
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
421
- <title>' << year_s << ' - ' << @dir_path_basename_s << '</title>
422
- <link rel="stylesheet" href="style.css" type="text/css" />
423
- </head>
424
- <body>
425
- <h1><a href=".">' << @dir_path_basename_s << '</a></h1>
426
- <p>Generated @ ' << DateTime.now.strftime('%Y-%m-%d %H:%M:%S') << ' by <a href="' << HOMEPAGE << '">' << NAME << '</a> v' << VERSION << '</p>
427
-
428
- <h2>Year: ' << year_s << '</h2>
429
- <table class="list">
430
- <tr>
431
- <th class="left">Month</th>
432
- <th class="right">Revenue</th>
433
- <th class="right">Expense</th>
434
- <th class="right">Balance</th>
435
- <th colspan="' << categories_available.count.to_s << '">' << categories_available.count.to_s << ' Categories</th>
436
- </tr>
437
- <tr>
438
- <th colspan="4">&nbsp;</th>
439
- ')
440
- categories_available.each do |category|
441
- year_file.write(%(<th class="right">#{category}</th>))
442
- end
443
- year_file.write('</tr>')
444
-
445
416
  revenue_year = 0.0
446
417
  expense_year = 0.0
447
418
  balance_year = 0.0
@@ -451,6 +422,8 @@ module TheFox
451
422
 
452
423
  @logger.info("generate year #{year}")
453
424
 
425
+ tpl_months = Array.new()
426
+
454
427
  month_files = @data_path
455
428
  .children
456
429
  .sort
@@ -472,11 +445,6 @@ module TheFox
472
445
  if date_start && date_end
473
446
  file_date_start = Date.parse("#{year}-#{month_n}-01")
474
447
  file_date_end = Date.parse("#{year}-#{month_n}-01").next_month.prev_day
475
-
476
- if date_end < file_date_start ||
477
- date_start > file_date_end
478
- next
479
- end
480
448
  end
481
449
 
482
450
  revenue_month = 0.0
@@ -501,39 +469,11 @@ module TheFox
501
469
  }
502
470
  write_html = true
503
471
  end
504
- unless month_file_path.exist?
472
+ if not month_file_path.exist?
505
473
  write_html = true
506
474
  end
507
475
 
508
- if write_html
509
- @logger.debug("file: #{month_file_name_s} (from #{file_name_s})")
510
-
511
- month_file = File.open(month_file_path, 'w')
512
- month_file.write('
513
- <html>
514
- <head>
515
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
516
- <title>' << month_s << ' ' << year_s << ' - ' << @dir_path_basename_s << '</title>
517
- <link rel="stylesheet" href="style.css" type="text/css" />
518
- </head>
519
- <body>
520
- <h1><a href=".">' << @dir_path_basename_s << '</a></h1>
521
- <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>
522
-
523
- <h2>Month: ' << month_s << ' <a href="' << year_file_name_s << '">' << year_s << '</a></h2>
524
- <table class="list">
525
- <tr>
526
- <th class="left">#</th>
527
- <th class="left">Date</th>
528
- <th class="left first_column">Title</th>
529
- <th class="right">Revenue</th>
530
- <th class="right">Expense</th>
531
- <th class="right">Balance</th>
532
- <th class="right">Category</th>
533
- <th class="left">Comment</th>
534
- </tr>
535
- ')
536
- end
476
+ tpl_days = Array.new()
537
477
 
538
478
  data['days'].sort.each do |day_name, day_items|
539
479
  day_items.each do |entry|
@@ -557,20 +497,19 @@ module TheFox
557
497
  category_out = entry['category'] == 'default' ? '&nbsp;' : entry['category']
558
498
  comment_out = entry['comment'] == '' ? '&nbsp;' : entry['comment']
559
499
 
560
- if write_html
561
- month_file.write('
562
- <tr>
563
- <td valign="top" class="left">' << entry_n.to_s << '</td>
564
- <td valign="top" class="left">' << entry_date_s << '</td>
565
- <td valign="top" class="left">' << entry['title'][0, 50] << '</td>
566
- <td valign="top" class="right">' << revenue_out << '</td>
567
- <td valign="top" class="right red">' << expense_out << '</td>
568
- <td valign="top" class="right ' << (entry['balance'] < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % entry['balance'] << '</td>
569
- <td valign="top" class="right">' << category_out << '</td>
570
- <td valign="top" class="left">' << comment_out << '</td>
571
- </tr>
572
- ')
573
- end
500
+ tpl_days << {
501
+ 'entry_n' => entry_n.to_s,
502
+ 'entry_date_s' => entry_date_s,
503
+ 'title' => entry['title'][0, 50],
504
+ 'revenue_out' => revenue_out,
505
+ 'expense_out' => expense_out,
506
+
507
+ 'balance_class' => entry['balance'] < 0 ? 'red' : '',
508
+ 'balance' => NUMBER_FORMAT % entry['balance'],
509
+
510
+ 'category_out' => category_out,
511
+ 'comment_out' => comment_out,
512
+ }
574
513
  end
575
514
  end
576
515
 
@@ -595,34 +534,51 @@ module TheFox
595
534
  balance_class = 'red'
596
535
  end
597
536
  if write_html
598
- month_file.write('
599
- <tr>
600
- <th>&nbsp;</th>
601
- <th>&nbsp;</th>
602
- <th class="left"><b>TOTAL</b></th>
603
- <th class="right">' << NUMBER_FORMAT % revenue_month << '</th>
604
- <th class="right red">' << NUMBER_FORMAT % expense_month << '</th>
605
- <th class="right ' << balance_class << '">' << NUMBER_FORMAT % balance_month << '</th>
606
- <th>&nbsp;</th>
607
- <th>&nbsp;</th>
608
- </tr>
609
- </table>')
610
- month_file.write('</body></html>')
537
+ @logger.debug("file: #{month_file_name_s} (from #{file_name_s})")
538
+
539
+ month_file = File.open(month_file_path, 'w')
540
+ month_file.write(month_liquid_tpl.render({
541
+ 'month_s' => month_s,
542
+ 'year_s' => year_s,
543
+ 'year_file_name_s' => year_file_name_s,
544
+ 'dir_path' => @dir_path_basename_s,
545
+ 'file_name_s' => file_name_s,
546
+
547
+ 'now' => DateTime.now.strftime(DATETIME_FORMAT),
548
+
549
+ 'app_homepage' => HOMEPAGE,
550
+ 'app_name' => NAME,
551
+ 'app_version' => VERSION,
552
+
553
+ 'revenue_month' => NUMBER_FORMAT % revenue_month,
554
+ 'expense_month' => NUMBER_FORMAT % expense_month,
555
+ 'balance_class' => balance_class,
556
+ 'balance_month' => NUMBER_FORMAT % balance_month,
557
+
558
+ 'days' => tpl_days,
559
+ }))
611
560
  month_file.close
612
561
  end
613
562
 
614
- year_file.write('
615
- <tr>
616
- <td class="left"><a href="' << month_file_name_s << '">' << month_s << '</a></td>
617
- <td class="right">' << NUMBER_FORMAT % revenue_month << '</td>
618
- <td class="right red">' << NUMBER_FORMAT % expense_month << '</td>
619
- <td class="right ' << balance_class << '">' << NUMBER_FORMAT % balance_month << '</td>')
620
- categories_available.each do |category|
563
+ tpl_months_categories = categories_available.map{ |category|
621
564
  category_balance = categories_month_balance[category]
622
- year_file.write('<td class="right ' << (category_balance < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % category_balance << '</td>')
623
- end
624
- year_file.write('</tr>')
625
- end
565
+
566
+ {
567
+ 'class' => category_balance < 0 ? 'red' : '',
568
+ 'balance' => category_balance > 0.0 ? NUMBER_FORMAT % category_balance : '&nbsp;',
569
+ }
570
+ }
571
+
572
+ tpl_months << {
573
+ 'month_file_name_s' => month_file_name_s,
574
+ 'month_s' => month_s,
575
+ 'revenue_month' => NUMBER_FORMAT % revenue_month,
576
+ 'expense_month' => NUMBER_FORMAT % expense_month,
577
+ 'balance_class' => balance_class,
578
+ 'balance_month' => NUMBER_FORMAT % balance_month,
579
+ 'categories' => tpl_months_categories,
580
+ }
581
+ end # month_files.each
626
582
 
627
583
  year_total
628
584
  .sort
@@ -630,27 +586,33 @@ module TheFox
630
586
  item[1].balance_total = (sum + item[1].balance).round(NUMBER_ROUND)
631
587
  }
632
588
 
633
- year_file.write('
634
- <tr>
635
- <th class="left"><b>TOTAL</b></th>
636
- <th class="right">' << NUMBER_FORMAT % revenue_year << '</th>
637
- <th class="right red">' << NUMBER_FORMAT % expense_year << '</th>
638
- <th class="right ' << (balance_year < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % balance_year << '</th>')
639
- categories_available.each do |category|
640
- category_balance = categories_year_balance[category]
641
- year_file.write('<td class="right ' << (category_balance < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % category_balance << '</td>')
642
- end
643
-
644
- year_file.write('
645
- </tr>
646
- </table>
647
- ')
589
+ categories_year_balance_formatted = categories_available.map{ |category|
590
+ [category, {
591
+ 'balance' => NUMBER_FORMAT % categories_year_balance[category],
592
+ 'class' => categories_year_balance[category] < 0 ? 'red' : '',
593
+ }]
594
+ }.to_h
648
595
 
649
- year_file.write(%{<p><img src="year_#{year_s}.png"></p>})
650
- year_file.write('</body></html>')
596
+ year_file = File.open(year_file_path, 'w')
597
+ year_file.write(year_liquid_tpl.render({
598
+ 'year_s' => year_s,
599
+ 'dir_path' => @dir_path_basename_s,
600
+ 'now' => DateTime.now.strftime(DATETIME_FORMAT),
601
+ 'app_homepage' => HOMEPAGE,
602
+ 'app_name' => NAME,
603
+ 'app_version' => VERSION,
604
+ 'categories_available_count' => categories_available.count.to_s,
605
+ 'categories_available' => categories_available,
606
+ 'revenue_year' => NUMBER_FORMAT % revenue_year,
607
+ 'expense_year' => NUMBER_FORMAT % expense_year,
608
+ 'balance_year_class' => balance_year < 0 ? 'red' : '',
609
+ 'balance_year' => NUMBER_FORMAT % balance_year,
610
+ 'categories_year_balance_formatted' => categories_year_balance_formatted,
611
+ 'months' => tpl_months,
612
+ }))
651
613
  year_file.close
652
614
 
653
- yeardat_file_path = Pathname.new("year_#{year_s}.dat").expand_path(@tmp_path)
615
+ yeardat_file_path = Pathname.new("year_#{year_s}.dat").expand_path(@tmp_path).to_s
654
616
  yeardat_file = File.new(yeardat_file_path, 'w')
655
617
  yeardat_file.write(year_total
656
618
  .sort{ |a, b| a[0] <=> b[0] }
@@ -661,35 +623,13 @@ module TheFox
661
623
 
662
624
  gnuplot_file_path = Pathname.new("year_#{year_s}.gp").expand_path(@tmp_path)
663
625
  gnuplot_file = File.new(gnuplot_file_path, 'w')
664
- gnuplot_file.puts("set title 'Year #{year_s}'")
665
- gnuplot_file.puts("set xlabel 'Months'")
666
- gnuplot_file.puts("set ylabel 'Euro'")
667
- gnuplot_file.puts("set grid")
668
- gnuplot_file.puts("set key below center horizontal noreverse enhanced autotitle box dashtype solid")
669
- gnuplot_file.puts("set tics out nomirror")
670
- gnuplot_file.puts("set border 3 front linetype black linewidth 1.0 dashtype solid")
671
-
672
- gnuplot_file.puts("set timefmt '%Y-%m'")
673
- gnuplot_file.puts("set xdata time")
674
- gnuplot_file.puts("set format x '%b'")
675
- gnuplot_file.puts("set xrange ['#{year_s}-01-01':'#{year_s}-12-31']")
676
- gnuplot_file.puts("set xtics '#{year_s}-01-01', 2592000, '#{year_s}-12-31'")
677
- # gnuplot_file.puts("set yrange [-#{year_min_r}:#{year_max_r}]")
678
- gnuplot_file.puts("set autoscale y")
679
-
680
- gnuplot_file.puts("set style line 1 linecolor rgb '#00ff00' linewidth 2 linetype 1 pointtype 2")
681
- gnuplot_file.puts("set style line 2 linecolor rgb '#ff0000' linewidth 2 linetype 1 pointtype 2")
682
- gnuplot_file.puts("set style line 3 linecolor rgb '#000000' linewidth 2 linetype 1 pointtype 2")
683
- gnuplot_file.puts("set style line 4 linecolor rgb '#0000ff' linewidth 2 linetype 1 pointtype 2")
684
- gnuplot_file.puts("set style data linespoints")
685
- gnuplot_file.puts("set terminal png enhanced")
686
- gnuplot_file.puts("set output '" << File.expand_path("year_#{year_s}.png", html_path) << "'")
687
- gnuplot_file.puts("plot sum = 0, \\")
688
- gnuplot_file.puts("\t'#{yeardat_file_path}' using 1:2 linestyle 1 title 'Revenue', \\")
689
- gnuplot_file.puts("\t'' using 1:3 linestyle 2 title 'Expense', \\")
690
- gnuplot_file.puts("\t'' using 1:4 linestyle 3 title 'Balance', \\")
691
- gnuplot_file.puts("\t'' using 1:5 linestyle 4 title '∑ Balance'")
626
+ gnuplot_file.write(gnuplot_year_liquid_tpl.render({
627
+ 'year_s' => year_s,
628
+ 'yeardat_file_path' => yeardat_file_path,
629
+ 'output_path' => File.expand_path('year_%s.png' % year_s, html_path),
630
+ }))
692
631
  gnuplot_file.close
632
+
693
633
  system("gnuplot #{gnuplot_file_path} &> /dev/null")
694
634
 
695
635
  years_total[year_s] = ::OpenStruct.new({
@@ -701,60 +641,41 @@ module TheFox
701
641
  end
702
642
 
703
643
  years_total.sort.inject(0.0){ |sum, item| item[1].balance_total = (sum + item[1].balance).round(NUMBER_ROUND) }
644
+ balance_total = years_total.inject(0.0){ |sum, item| sum + item[1].balance }
704
645
 
705
- index_file_path = Pathname.new('index.html').expand_path(html_path)
706
- index_file = File.open(index_file_path, 'w')
707
- index_file.write('
708
- <html>
709
- <head>
710
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
711
- <title>' << @dir_path_basename_s << '</title>
712
- <link rel="stylesheet" href="style.css" type="text/css" />
713
- </head>
714
- <body>
715
- <h1>' << @dir_path_basename_s << '</h1>
716
- <p>Generated @ ' << DateTime.now.strftime('%F %T') << ' by <a href="' << HOMEPAGE << '">' << NAME << '</a> v' << VERSION << '</p>
717
- ')
718
-
719
- # Write total to index.html file.
720
- index_file.write('
721
- <table class="list">
722
- <tr>
723
- <th class="left">Year</th>
724
- <th class="right">Revenue</th>
725
- <th class="right">Expense</th>
726
- <th class="right">Balance</th>
727
- <th class="right">Balance &#8721;</th>
728
- </tr>')
729
-
730
- # Write years total to index.html file.
731
- years_total.each do |year_name, year_data|
732
- index_file.write('
733
- <tr>
734
- <td class="left"><a href="year_' << year_name << '.html">' << year_name << '</a></td>
735
- <td class="right">' << NUMBER_FORMAT % year_data.revenue << '</td>
736
- <td class="right red">' << NUMBER_FORMAT % year_data.expense << '</td>
737
- <td class="right ' << (year_data.balance < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % year_data.balance << '</td>
738
- <td class="right ' << (year_data.balance_total < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % year_data.balance_total << '</td>
739
- </tr>')
740
- end
646
+ index_liquid_tpl_src = Pathname.new('views/index.liquid').expand_path(@resources_root).to_s
647
+ index_liquid_tpl = Liquid::Template.parse(File.read(index_liquid_tpl_src))
741
648
 
742
- balance_total = years_total.inject(0.0){ |sum, item| sum + item[1].balance }
649
+ years_total_formatted = years_total.map{ |year_name, year_data|
650
+ {
651
+ 'name' => year_name,
652
+ 'revenue' => NUMBER_FORMAT % year_data.revenue,
653
+ 'expense' => NUMBER_FORMAT % year_data.expense,
654
+
655
+ 'balance' => NUMBER_FORMAT % year_data.balance,
656
+ 'balance_class' => year_data.balance < 0 ? 'red' : '',
657
+
658
+ 'balance_total' => NUMBER_FORMAT % year_data.balance_total,
659
+ 'balance_total_class' => year_data.balance_total < 0 ? 'red' : '',
660
+ }
661
+ }
743
662
 
744
- index_file.write('
745
- <tr>
746
- <th class="left"><b>TOTAL</b></th>
747
- <th class="right">' << NUMBER_FORMAT % years_total.inject(0.0){ |sum, item| sum + item[1].revenue } << '</th>
748
- <th class="right red">' << NUMBER_FORMAT % years_total.inject(0.0){ |sum, item| sum + item[1].expense } << '</th>
749
- <th class="right ' << (balance_total < 0 ? 'red' : '') << '">' << NUMBER_FORMAT % balance_total << '</th>
750
- <th>&nbsp;</th>
751
- </tr>
752
- </table>
753
-
754
- <p><img src="total.png"></p>
755
- </body>
756
- </html>
757
- ')
663
+ index_file_path = Pathname.new('index.html').expand_path(html_path)
664
+ index_file = File.open(index_file_path, 'w')
665
+ index_file.write(index_liquid_tpl.render({
666
+ 'dir_path' => @dir_path_basename_s,
667
+ 'now' => DateTime.now.strftime(DATETIME_FORMAT),
668
+ 'app_homepage' => HOMEPAGE,
669
+ 'app_name' => NAME,
670
+ 'app_version' => VERSION,
671
+
672
+ 'years_total_formatted' => years_total_formatted,
673
+
674
+ 'revenue_total' => NUMBER_FORMAT % years_total.inject(0.0){ |sum, item| sum + item[1].revenue },
675
+ 'expense_total' => NUMBER_FORMAT % years_total.inject(0.0){ |sum, item| sum + item[1].expense },
676
+ 'balance_total' => NUMBER_FORMAT % balance_total,
677
+ 'balance_total_class' => balance_total < 0 ? 'red' : '',
678
+ }))
758
679
  index_file.close
759
680
 
760
681
  store = YAML::Store.new(html_options_path)
@@ -775,36 +696,23 @@ module TheFox
775
696
  totaldat_file_c = totaldat_file_c.join("\n")
776
697
 
777
698
  # DAT file for GNUPlot.
778
- totaldat_file_path = Pathname.new('total.dat').expand_path(@tmp_path)
699
+ totaldat_file_path = Pathname.new('total.dat').expand_path(@tmp_path).to_s
779
700
  totaldat_file = File.new(totaldat_file_path, 'w')
780
701
  totaldat_file.write(totaldat_file_c)
781
702
  totaldat_file.close
782
703
 
783
704
  # Generate image with GNUPlot.
784
- png_file_path = Pathname.new('total.png').expand_path(html_path)
705
+ png_file_path = Pathname.new('total.png').expand_path(html_path).to_s
706
+
707
+ gnuplot_total_liquid_tpl_src = Pathname.new('gnuplot/total_config.liquid').expand_path(@resources_root).to_s
708
+ gnuplot_total_liquid_tpl = Liquid::Template.parse(File.read(gnuplot_total_liquid_tpl_src))
785
709
 
786
710
  gnuplot_file_path = Pathname.new('total.gp').expand_path(@tmp_path)
787
711
  gnuplot_file = File.new(gnuplot_file_path, 'w')
788
- gnuplot_file.puts("set title 'Total'")
789
- gnuplot_file.puts("set xlabel 'Years'")
790
- gnuplot_file.puts("set ylabel 'Euro'")
791
- gnuplot_file.puts("set grid")
792
- gnuplot_file.puts("set key below center horizontal noreverse enhanced autotitle box dashtype solid")
793
- gnuplot_file.puts("set tics out nomirror")
794
- gnuplot_file.puts("set border 3 front linetype black linewidth 1.0 dashtype solid")
795
- gnuplot_file.puts("set xtics 1")
796
- gnuplot_file.puts("set style line 1 linecolor rgb '#00ff00' linewidth 2 linetype 1 pointtype 2")
797
- gnuplot_file.puts("set style line 2 linecolor rgb '#ff0000' linewidth 2 linetype 1 pointtype 2")
798
- gnuplot_file.puts("set style line 3 linecolor rgb '#000000' linewidth 2 linetype 1 pointtype 2")
799
- gnuplot_file.puts("set style line 4 linecolor rgb '#0000ff' linewidth 2 linetype 1 pointtype 2")
800
- gnuplot_file.puts("set style data linespoints")
801
- gnuplot_file.puts("set terminal png enhanced")
802
- gnuplot_file.puts("set output '#{png_file_path}'")
803
- gnuplot_file.puts("plot sum = 0, \\")
804
- gnuplot_file.puts("\t'#{totaldat_file_path}' using 1:2 linestyle 1 title 'Revenue', \\")
805
- gnuplot_file.puts("\t'' using 1:3 linestyle 2 title 'Expense', \\")
806
- gnuplot_file.puts("\t'' using 1:4 linestyle 3 title 'Balance', \\")
807
- gnuplot_file.puts("\t'' using 1:5 linestyle 4 title '∑ Balance'")
712
+ gnuplot_file.write(gnuplot_total_liquid_tpl.render({
713
+ 'png_file_path' => png_file_path,
714
+ 'totaldat_file_path' => totaldat_file_path,
715
+ }))
808
716
  gnuplot_file.close
809
717
 
810
718
  system("gnuplot #{gnuplot_file_path} &> /dev/null")
@@ -956,21 +864,21 @@ module TheFox
956
864
 
957
865
  # Create all needed subdirectories for this wallet.
958
866
  def create_dirs
959
- unless @dir_path.exist?
867
+ if not @dir_path.exist?
960
868
  @dir_path.mkpath
961
869
  end
962
870
 
963
- unless @data_path.exist?
871
+ if not @data_path.exist?
964
872
  @data_path.mkpath
965
873
  end
966
874
 
967
- unless @tmp_path.exist?
875
+ if not @tmp_path.exist?
968
876
  @tmp_path.mkpath
969
877
  end
970
878
 
971
879
  # Ignore all files in wallet/tmp.
972
880
  tmp_gitignore_path = Pathname.new('.gitignore').expand_path(@tmp_path)
973
- unless tmp_gitignore_path.exist?
881
+ if not tmp_gitignore_path.exist?
974
882
  gitignore_file = File.open(tmp_gitignore_path, 'w')
975
883
  gitignore_file.write('*')
976
884
  gitignore_file.close
@@ -0,0 +1,22 @@
1
+
2
+ /* Style */
3
+
4
+ html {
5
+ -webkit-text-size-adjust: none;
6
+ }
7
+ table.list, table.list th, table.list td {
8
+ border: 1px solid black;
9
+ }
10
+ th.left, td.left {
11
+ text-align: left;
12
+ }
13
+ th.right, td.right {
14
+ text-align: right;
15
+ }
16
+ th.first_column {
17
+ min-width: 180px;
18
+ width: 180px;
19
+ }
20
+ th.red, td.red {
21
+ color: #ff0000;
22
+ }
@@ -0,0 +1,25 @@
1
+ set title 'Total'
2
+
3
+ set xlabel 'Years'
4
+ set ylabel 'Euro'
5
+
6
+ set grid
7
+ set key below center horizontal noreverse enhanced autotitle box dashtype solid
8
+ set tics out nomirror
9
+ set border 3 front linetype black linewidth 1.0 dashtype solid
10
+ set xtics 1
11
+
12
+ set style line 1 linecolor rgb '#00ff00' linewidth 2 linetype 1 pointtype 2
13
+ set style line 2 linecolor rgb '#ff0000' linewidth 2 linetype 1 pointtype 2
14
+ set style line 3 linecolor rgb '#000000' linewidth 2 linetype 1 pointtype 2
15
+ set style line 4 linecolor rgb '#0000ff' linewidth 2 linetype 1 pointtype 2
16
+ set style data linespoints
17
+
18
+ set terminal png enhanced
19
+ set output '{{ png_file_path }}'
20
+
21
+ plot sum = 0, \
22
+ '{{ totaldat_file_path }}' using 1:2 linestyle 1 title 'Revenue', \
23
+ '' using 1:3 linestyle 2 title 'Expense', \
24
+ '' using 1:4 linestyle 3 title 'Balance', \
25
+ '' using 1:5 linestyle 4 title '∑ Balance'
@@ -0,0 +1,30 @@
1
+ set title 'Year {{ year_s }}'
2
+ set xlabel 'Months'
3
+ set ylabel 'Euro'
4
+ set grid
5
+ set key below center horizontal noreverse enhanced autotitle box dashtype solid
6
+ set tics out nomirror
7
+ set border 3 front linetype black linewidth 1.0 dashtype solid
8
+
9
+ set timefmt '%Y-%m'
10
+ set xdata time
11
+ set format x '%b'
12
+ set xrange ['{{ year_s }}-01-01':'{{ year_s }}-12-31']
13
+ set xtics '{{ year_s }}-01-01', 2592000, '{{ year_s }}-12-31'
14
+ set autoscale y
15
+
16
+ set style line 1 linecolor rgb '#00ff00' linewidth 2 linetype 1 pointtype 2
17
+ set style line 2 linecolor rgb '#ff0000' linewidth 2 linetype 1 pointtype 2
18
+ set style line 3 linecolor rgb '#000000' linewidth 2 linetype 1 pointtype 2
19
+ set style line 4 linecolor rgb '#0000ff' linewidth 2 linetype 1 pointtype 2
20
+ set style data linespoints
21
+
22
+ set terminal png enhanced
23
+
24
+ set output '{{ output_path }}'
25
+
26
+ plot sum = 0, \
27
+ '{{ yeardat_file_path }}' using 1:2 linestyle 1 title 'Revenue', \
28
+ '' using 1:3 linestyle 2 title 'Expense', \
29
+ '' using 1:4 linestyle 3 title 'Balance', \
30
+ '' using 1:5 linestyle 4 title '∑ Balance'
@@ -0,0 +1,44 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
5
+ <title>{{ dir_path }}</title>
6
+ <link rel="stylesheet" href="style.css" type="text/css" />
7
+ </head>
8
+
9
+ <body>
10
+ <h1><a href="./index.html">{{ dir_path }}</a></h1>
11
+
12
+ <p>Generated @ {{ now }} by <a href="{{ app_homepage }}">{{ app_name }}</a> v{{ app_version }}</p>
13
+
14
+ <table class="list">
15
+ <tr>
16
+ <th class="left">Year</th>
17
+ <th class="right">Revenue</th>
18
+ <th class="right">Expense</th>
19
+ <th class="right">Balance</th>
20
+ <th class="right">Balance &#8721;</th>
21
+ </tr>
22
+
23
+ {% for year in years_total_formatted %}
24
+ <tr>
25
+ <td class="left"><a href="year_{{ year['name'] }}.html">{{ year['name'] }}</a></td>
26
+ <td class="right">{{ year['revenue'] }}</td>
27
+ <td class="right red">{{ year['expense'] }}</td>
28
+ <td class="right {{ year['balance_class'] }}">{{ year['balance'] }}</td>
29
+ <td class="right {{ year['balance_total_class'] }}">{{ year['balance_total'] }}</td>
30
+ </tr>
31
+ {% endfor %}
32
+
33
+ <tr>
34
+ <th class="left"><b>TOTAL</b></th>
35
+ <th class="right">{{ revenue_total }}</th>
36
+ <th class="right red">{{ expense_total }}</th>
37
+ <th class="right {{ balance_total_class }}">{{ balance_total }}</th>
38
+ <th>&nbsp;</th>
39
+ </tr>
40
+ </table>
41
+
42
+ <p><img src="total.png"></p>
43
+ </body>
44
+ </html>
@@ -0,0 +1,54 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
5
+ <title>{{ month_s }} {{ year_s }} - {{ dir_path }}</title>
6
+ <link rel="stylesheet" href="style.css" type="text/css" />
7
+ </head>
8
+
9
+ <body>
10
+ <h1><a href="./index.html">{{ dir_path }}</a></h1>
11
+
12
+ <p>Generated @ {{ now }} by <a href="{{ app_homepage }}">{{ app_name }}</a> v{{ app_version }} from <code>{{ file_name_s }}</code></p>
13
+
14
+ <h2>Month: {{ month_s }} <a href="{{ year_file_name_s }}">{{ year_s }}</a></h2>
15
+
16
+ <table class="list">
17
+ <tr>
18
+ <th class="left">#</th>
19
+ <th class="left">Date</th>
20
+ <th class="left first_column">Title</th>
21
+ <th class="right">Revenue</th>
22
+ <th class="right">Expense</th>
23
+ <th class="right">Balance</th>
24
+ <th class="right">Category</th>
25
+ <th class="left">Comment</th>
26
+ </tr>
27
+
28
+ {% for day in days %}
29
+ <tr>
30
+ <td valign="top" class="left">{{ day['entry_n'] }}</td>
31
+ <td valign="top" class="left">{{ day['entry_date_s'] }}</td>
32
+ <td valign="top" class="left">{{ day['title'] }}</td>
33
+ <td valign="top" class="right">{{ day['revenue_out'] }}</td>
34
+ <td valign="top" class="right red">{{ day['expense_out'] }}</td>
35
+ <td valign="top" class="right {{ day['balance_class'] }}">{{ day['balance'] }}</td>
36
+ <td valign="top" class="right">{{ day['category_out'] }}</td>
37
+ <td valign="top" class="left">{{ day['comment_out'] }}</td>
38
+ </tr>
39
+ {% endfor %}
40
+
41
+ <tr>
42
+ <th>&nbsp;</th>
43
+ <th>&nbsp;</th>
44
+ <th class="left"><b>TOTAL</b></th>
45
+ <th class="right">{{ revenue_month }}</th>
46
+ <th class="right red">{{ expense_month }}</th>
47
+ <th class="right {{ balance_class }}">{{ balance_month }}</th>
48
+ <th>&nbsp;</th>
49
+ <th>&nbsp;</th>
50
+ </tr>
51
+ </table>
52
+
53
+ </body>
54
+ </html>
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
5
+ <title>{{ year_s }} - {{ dir_path }}</title>
6
+ <link rel="stylesheet" href="style.css" type="text/css" />
7
+ </head>
8
+
9
+ <body>
10
+ <h1><a href="./index.html">{{ dir_path }}</a></h1>
11
+
12
+ <p>Generated @ {{ now }} by <a href="{{ app_homepage }}">{{ app_name }}</a> v{{ app_version }}</p>
13
+
14
+ <h2>Year: {{ year_s }}</h2>
15
+ <table class="list">
16
+ <tr>
17
+ <th class="left">Month</th>
18
+ <th class="right">Revenue</th>
19
+ <th class="right">Expense</th>
20
+ <th class="right">Balance</th>
21
+ <th colspan="{{ categories_available_count }}">{{ categories_available_count }} Categories</th>
22
+ </tr>
23
+ <tr>
24
+ <th colspan="4">&nbsp;</th>
25
+
26
+ {% for category in categories_available %}
27
+ <th class="right">{{ category }}</th>
28
+ {% endfor %}
29
+ </tr>
30
+
31
+ {% for month in months %}
32
+ <tr>
33
+ <td class="left"><a href="{{ month['month_file_name_s'] }}">{{ month['month_s'] }}</a></td>
34
+ <td class="right">{{ month['revenue_month'] }}</td>
35
+ <td class="right red">{{ month['expense_month'] }}</td>
36
+ <td class="right {{ month['balance_class'] }}">{{ month['balance_month'] }}</td>
37
+
38
+ {% for category in month['categories'] %}
39
+ <td class="right {{ category['class'] }}">{{ category['balance'] }}</td>
40
+ {% endfor %}
41
+ </tr>
42
+ {% endfor %}
43
+
44
+ <tr>
45
+ <th class="left"><b>TOTAL</b></th>
46
+ <th class="right">{{ revenue_year }}</th>
47
+ <th class="right red">{{ expense_year }}</th>
48
+ <th class="right {{ balance_year_class }}">{{ balance_year }}</th>
49
+
50
+ {% for category in categories_available %}
51
+ <th class="right {{ categories_year_balance_formatted[category]['class'] }}">{{ categories_year_balance_formatted[category]['balance'] }}</th>
52
+ {% endfor %}
53
+ </tr>
54
+ </table>
55
+
56
+ <p><img src="year_{{ year_s }}.png"></p>
57
+ </body>
58
+ </html>
@@ -21,12 +21,13 @@ Gem::Specification.new do |spec|
21
21
  spec.bindir = 'bin'
22
22
  spec.executables = ['wallet']
23
23
  spec.require_paths = ['lib']
24
- spec.required_ruby_version = '>=2.1.0'
24
+ spec.required_ruby_version = '>=2.2.0'
25
25
 
26
26
  spec.add_development_dependency 'pry', '~>0.10'
27
27
  spec.add_development_dependency 'minitest', '~>5.7'
28
28
  spec.add_development_dependency 'simplecov', '~>0.12'
29
29
  spec.add_development_dependency 'simplecov-phpunit', '~>1.0'
30
+ spec.add_development_dependency 'liquid', '~>4.0'
30
31
 
31
32
  spec.add_runtime_dependency 'uuid', '~>2.3'
32
33
  end
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.18.0
4
+ version: 0.19.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: 2018-08-13 00:00:00.000000000 Z
11
+ date: 2018-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: liquid
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: uuid
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -95,7 +109,8 @@ files:
95
109
  - Gemfile
96
110
  - README.md
97
111
  - Vagrantfile
98
- - bin/build_coverage.sh
112
+ - bin/.gitignore
113
+ - bin/coverage.sh
99
114
  - bin/dev
100
115
  - bin/dev_data.sh
101
116
  - bin/dev_setup.sh
@@ -115,6 +130,12 @@ files:
115
130
  - lib/wallet/entry.rb
116
131
  - lib/wallet/version.rb
117
132
  - lib/wallet/wallet.rb
133
+ - resources/css/style.css
134
+ - resources/gnuplot/total_config.liquid
135
+ - resources/gnuplot/year_config.liquid
136
+ - resources/views/index.liquid
137
+ - resources/views/month.liquid
138
+ - resources/views/year.liquid
118
139
  - thefox-wallet.gemspec
119
140
  - wallet.sublime-project
120
141
  homepage: https://github.com/TheFox/wallet
@@ -129,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
150
  requirements:
130
151
  - - ">="
131
152
  - !ruby/object:Gem::Version
132
- version: 2.1.0
153
+ version: 2.2.0
133
154
  required_rubygems_version: !ruby/object:Gem::Requirement
134
155
  requirements:
135
156
  - - ">="