thefox-wallet 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +2 -1
 - data/.gitlab-ci.yml +4 -5
 - data/Gemfile +8 -0
 - data/Makefile +7 -2
 - data/Makefile.common +8 -6
 - data/README.md +1 -1
 - data/bin/dev +12 -0
 - data/bin/wallet +35 -22
 - data/lib/wallet/command.rb +6 -2
 - data/lib/wallet/command_add.rb +7 -4
 - data/lib/wallet/command_categories.rb +1 -3
 - data/lib/wallet/command_csv.rb +5 -4
 - data/lib/wallet/command_html.rb +10 -3
 - data/lib/wallet/command_list.rb +38 -30
 - data/lib/wallet/entry.rb +2 -2
 - data/lib/wallet/version.rb +2 -2
 - data/lib/wallet/wallet.rb +180 -176
 - data/thefox-wallet.gemspec +2 -1
 - metadata +20 -6
 - data/bin/.gitignore +0 -1
 
    
        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 : 
     | 
| 
      
 18 
     | 
    
         
            +
            			attr_reader :dir_path
         
     | 
| 
       22 
19 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
            			def initialize(dir_path =  
     | 
| 
      
 20 
     | 
    
         
            +
            			def initialize(dir_path = nil)
         
     | 
| 
       24 
21 
     | 
    
         
             
            				@exit = false
         
     | 
| 
       25 
22 
     | 
    
         
             
            				@logger = nil
         
     | 
| 
       26 
     | 
    
         
            -
            				@dir_path = dir_path
         
     | 
| 
       27 
     | 
    
         
            -
            				@ 
     | 
| 
       28 
     | 
    
         
            -
            				@ 
     | 
| 
       29 
     | 
    
         
            -
            				@ 
     | 
| 
      
 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 =  
     | 
| 
      
 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 
     | 
    
         
            -
            					 
     | 
| 
       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 
     | 
    
         
            -
            				 
     | 
| 
       63 
     | 
    
         
            -
            				 
     | 
| 
       64 
     | 
    
         
            -
            				 
     | 
| 
      
 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 
     | 
| 
       83 
     | 
    
         
            -
            						file = @transaction_files[ 
     | 
| 
      
 72 
     | 
    
         
            +
            					if @transaction_files[dbfile_basename_s]
         
     | 
| 
      
 73 
     | 
    
         
            +
            						file = @transaction_files[dbfile_basename_s]['file']
         
     | 
| 
       84 
74 
     | 
    
         
             
            					else
         
     | 
| 
       85 
     | 
    
         
            -
            						if  
     | 
| 
      
 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[ 
     | 
| 
       91 
     | 
    
         
            -
            							'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[ 
     | 
| 
      
 97 
     | 
    
         
            +
            					@transaction_files[dbfile_basename_s]['file'] = file
         
     | 
| 
       108 
98 
     | 
    
         
             
            				else
         
     | 
| 
       109 
     | 
    
         
            -
            					 
     | 
| 
       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  
     | 
| 
       134 
     | 
    
         
            -
            						 
     | 
| 
      
 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[ 
     | 
| 
      
 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 
     | 
    
         
            -
            				 
     | 
| 
      
 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  
     | 
| 
       344 
     | 
    
         
            -
            					if  
     | 
| 
      
 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 
     | 
    
         
            -
            					 
     | 
| 
      
 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 
     | 
    
         
            -
            				 
     | 
| 
      
 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 =  
     | 
| 
      
 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 =  
     | 
| 
      
 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>' << @ 
     | 
| 
      
 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>' << @ 
     | 
| 
       397 
     | 
    
         
            -
            							<p>Generated @ ' << DateTime.now.strftime('% 
     | 
| 
      
 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 
     | 
    
         
            -
            					 
     | 
| 
       404 
     | 
    
         
            -
            					 
     | 
| 
      
 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 << ' - ' << @ 
     | 
| 
      
 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">' << @ 
     | 
| 
       416 
     | 
    
         
            -
            								<p>Generated @ ' << DateTime.now.strftime('%Y-%m-%d %H:%M:%S') << ' by 
     | 
| 
      
 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"> </th>
         
     | 
| 
       429 
413 
     | 
    
         
             
            					')
         
     | 
| 
       430 
414 
     | 
    
         
             
            					categories_available.each do |category|
         
     | 
| 
       431 
     | 
    
         
            -
            						year_file.write( 
     | 
| 
      
 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 
     | 
    
         
            -
            					 
     | 
| 
       443 
     | 
    
         
            -
            					 
     | 
| 
       444 
     | 
    
         
            -
            						 
     | 
| 
       445 
     | 
    
         
            -
            						 
     | 
| 
       446 
     | 
    
         
            -
            						 
     | 
| 
       447 
     | 
    
         
            -
            						 
     | 
| 
      
 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'] 
     | 
| 
       462 
     | 
    
         
            -
            							if html_options['changes'][ 
     | 
| 
       463 
     | 
    
         
            -
            								html_options['changes'][ 
     | 
| 
      
 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'][ 
     | 
| 
      
 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 
     | 
    
         
            -
            						 
     | 
| 
      
 473 
     | 
    
         
            +
            						unless month_file_path.exist?
         
     | 
| 
       473 
474 
     | 
    
         
             
            							generate_html = true
         
     | 
| 
       474 
475 
     | 
    
         
             
            						end
         
     | 
| 
       475 
476 
     | 
    
         | 
| 
       476 
477 
     | 
    
         
             
            						if generate_html
         
     | 
| 
       477 
     | 
    
         
            -
            							 
     | 
| 
      
 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 << ' - ' << @ 
     | 
| 
      
 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">' << @ 
     | 
| 
       489 
     | 
    
         
            -
            										<p>Generated @ ' << DateTime.now.strftime('%Y-%m-%d %H:%M:%S') << ' by  <a href="' <<  
     | 
| 
      
 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="' <<  
     | 
| 
      
 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 ?  
     | 
| 
       517 
     | 
    
         
            -
            								expense_out = entry['expense'] < 0 ?  
     | 
| 
      
 530 
     | 
    
         
            +
            								revenue_out = entry['revenue'] > 0 ? NUMBER_FORMAT % entry['revenue'] : ' '
         
     | 
| 
      
 531 
     | 
    
         
            +
            								expense_out = entry['expense'] < 0 ? NUMBER_FORMAT % entry['expense'] : ' '
         
     | 
| 
       518 
532 
     | 
    
         
             
            								category_out = entry['category'] == 'default' ? ' ' : entry['category']
         
     | 
| 
       519 
533 
     | 
    
         
             
            								comment_out = entry['comment'] == '' ? ' ' : 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">' <<  
     | 
| 
      
 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' : '') << '">' <<  
     | 
| 
      
 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> </th>
         
     | 
| 
       562 
576 
     | 
    
         
             
            										<th> </th>
         
     | 
| 
       563 
577 
     | 
    
         
             
            										<th class="left"><b>TOTAL</b></th>
         
     | 
| 
       564 
     | 
    
         
            -
            										<th class="right">' <<  
     | 
| 
       565 
     | 
    
         
            -
            										<th class="right red">' <<  
     | 
| 
       566 
     | 
    
         
            -
            										<th class="right ' << balance_class << '">' <<  
     | 
| 
      
 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> </th>
         
     | 
| 
       568 
582 
     | 
    
         
             
            										<th> </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="' <<  
     | 
| 
       578 
     | 
    
         
            -
            								<td class="right">' <<  
     | 
| 
       579 
     | 
    
         
            -
            								<td class="right red">' <<  
     | 
| 
       580 
     | 
    
         
            -
            								<td class="right ' << balance_class << '">' <<  
     | 
| 
      
 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' : '') << '">' <<  
     | 
| 
      
 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">' <<  
     | 
| 
       594 
     | 
    
         
            -
            								<th class="right red">' <<  
     | 
| 
       595 
     | 
    
         
            -
            								<th class="right ' << (balance_year < 0 ? 'red' : '') << '">' <<  
     | 
| 
      
 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' : '') << '">' <<  
     | 
| 
      
 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 =  
     | 
| 
      
 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 
     | 
    
         
            -
            					 
     | 
| 
       618 
     | 
    
         
            -
            					 
     | 
| 
       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",  
     | 
| 
      
 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  
     | 
| 
      
 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">' <<  
     | 
| 
       701 
     | 
    
         
            -
            							<td class="right red">' <<  
     | 
| 
       702 
     | 
    
         
            -
            							<td class="right ' << (year_data.balance < 0 ? 'red' : '') << '">' <<  
     | 
| 
       703 
     | 
    
         
            -
            							<td class="right ' << (year_data.balance_total < 0 ? 'red' : '') << '">' <<  
     | 
| 
      
 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">' <<  
     | 
| 
       713 
     | 
    
         
            -
            							<th class="right red">' <<  
     | 
| 
       714 
     | 
    
         
            -
            							<th class="right ' << (balance_total < 0 ? 'red' : '') << '">' <<  
     | 
| 
      
 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> </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 >  
     | 
| 
       735 
     | 
    
         
            -
            					totaldat_file_c = totaldat_file_c.slice(- 
     | 
| 
      
 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 =  
     | 
| 
      
 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 
     | 
    
         
            -
            				 
     | 
| 
      
 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 ' 
     | 
| 
      
 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  
     | 
| 
      
 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 
     | 
    
         
            -
            					 
     | 
| 
      
 789 
     | 
    
         
            +
            					@logger.debug("import row '#{id}' -- #{added ? 'YES' : 'NO'}") if @logger
         
     | 
| 
       800 
790 
     | 
    
         
             
            				end
         
     | 
| 
       801 
791 
     | 
    
         | 
| 
       802 
     | 
    
         
            -
            				 
     | 
| 
       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[ 
     | 
| 
       820 
     | 
    
         
            -
            						 
     | 
| 
      
 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 
     | 
    
         
            -
            									 
     | 
| 
       831 
     | 
    
         
            -
            									 
     | 
| 
       832 
     | 
    
         
            -
            									 
     | 
| 
      
 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 =  
     | 
| 
      
 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 
     | 
    
         
            -
            				 
     | 
| 
       884 
     | 
    
         
            -
            					 
     | 
| 
      
 870 
     | 
    
         
            +
            				unless @dir_path.exist?
         
     | 
| 
      
 871 
     | 
    
         
            +
            					@dir_path.mkpath
         
     | 
| 
       885 
872 
     | 
    
         
             
            				end
         
     | 
| 
       886 
873 
     | 
    
         | 
| 
       887 
     | 
    
         
            -
            				 
     | 
| 
       888 
     | 
    
         
            -
            					 
     | 
| 
      
 874 
     | 
    
         
            +
            				unless @data_path.exist?
         
     | 
| 
      
 875 
     | 
    
         
            +
            					@data_path.mkpath
         
     | 
| 
       889 
876 
     | 
    
         
             
            				end
         
     | 
| 
       890 
877 
     | 
    
         | 
| 
       891 
     | 
    
         
            -
            				 
     | 
| 
       892 
     | 
    
         
            -
            					 
     | 
| 
      
 878 
     | 
    
         
            +
            				unless @tmp_path.exist?
         
     | 
| 
      
 879 
     | 
    
         
            +
            					@tmp_path.mkpath
         
     | 
| 
       893 
880 
     | 
    
         
             
            				end
         
     | 
| 
       894 
881 
     | 
    
         | 
| 
       895 
     | 
    
         
            -
            				tmp_gitignore_path =  
     | 
| 
       896 
     | 
    
         
            -
            				 
     | 
| 
      
 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  
     | 
| 
      
 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 
     | 
    
         
            -
            				 
     | 
| 
      
 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  
     | 
| 
       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
         
     |