thefox-wallet 0.10.2 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +14 -0
- data/.travis.yml +3 -1
- data/README.md +1 -1
- data/bin/.gitignore +1 -0
- data/bin/wallet +19 -7
- data/lib/wallet/command.rb +2 -0
- data/lib/wallet/command_add.rb +6 -2
- data/lib/wallet/command_list.rb +1 -1
- data/lib/wallet/entry.rb +37 -5
- data/lib/wallet/version.rb +2 -2
- data/lib/wallet/wallet.rb +138 -85
- data/tests/tc_command_add.rb +5 -2
- data/tests/tc_entry.rb +18 -15
- data/tests/tc_wallet.rb +68 -30
- data/thefox-wallet.gemspec +2 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d1f5a83951ef2ecb169b980fb3d61db0c3e0ac8
|
4
|
+
data.tar.gz: a52d9f6d5e620ee048fba9ad7274267d720a11a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8e936c75fdf1e4bd126248f7269522b273809a5b1e08e15f1212a7f1a5f5d8c6e7f3d910b72bedc04c17f683602d8efdbc7bae3803163ebeb1a20e71cb0d730
|
7
|
+
data.tar.gz: 455e2ab933be930e0d4e17a4266dc2427f7360a8a9f9e4fe97a2c056f6d1fe42cb5c1c4f6ad2a90791408040c9e79f63ef73c54ba9b51a69b110a22ecf5fdb54
|
data/.editorconfig
ADDED
data/.travis.yml
CHANGED
data/README.md
CHANGED
data/bin/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
dev
|
data/bin/wallet
CHANGED
@@ -22,6 +22,10 @@ opts = OptionParser.new do |o|
|
|
22
22
|
options[:wallet_path] = path
|
23
23
|
end
|
24
24
|
|
25
|
+
o.on('--id <id>', 'ID used for the entry.') do |id|
|
26
|
+
options[:entry_id] = id
|
27
|
+
end
|
28
|
+
|
25
29
|
o.on('-t', '--title <title>', 'Title used for the entry.') do |title|
|
26
30
|
options[:entry_title] = title
|
27
31
|
end
|
@@ -63,10 +67,14 @@ opts = OptionParser.new do |o|
|
|
63
67
|
options[:path] = path
|
64
68
|
end
|
65
69
|
|
66
|
-
o.on('-i', 'Use some commands interactively.') do
|
70
|
+
o.on('-i', '--interactive', 'Use some commands interactively.') do
|
67
71
|
options[:is_interactively] = true
|
68
72
|
end
|
69
73
|
|
74
|
+
o.on('-f', '--force', 'Force add command.') do
|
75
|
+
options[:force] = true
|
76
|
+
end
|
77
|
+
|
70
78
|
o.on_tail('-V', '--version', 'Show version.') do
|
71
79
|
puts "#{::TheFox::Wallet::NAME} #{::TheFox::Wallet::VERSION} (#{::TheFox::Wallet::DATE})"
|
72
80
|
puts TheFox::Wallet::HOMEPAGE
|
@@ -83,10 +91,14 @@ ARGV << '-h' if ARGV.count == 0
|
|
83
91
|
commands = opts.parse(ARGV)
|
84
92
|
command_name = commands.shift
|
85
93
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
94
|
+
if command_name
|
95
|
+
begin
|
96
|
+
command = TheFox::Wallet::Command.create_by_name(command_name, options)
|
97
|
+
command.run
|
98
|
+
rescue Exception => e
|
99
|
+
puts "ERROR: #{e}"
|
100
|
+
exit 1
|
101
|
+
end
|
102
|
+
else
|
103
|
+
opts.parse(['-h'])
|
92
104
|
end
|
data/lib/wallet/command.rb
CHANGED
@@ -11,6 +11,7 @@ module TheFox::Wallet
|
|
11
11
|
def initialize(options = {})
|
12
12
|
@options = options || {}
|
13
13
|
@options[:wallet_path] ||= 'wallet'
|
14
|
+
@options[:entry_id] ||= nil
|
14
15
|
@options[:entry_title] ||= nil
|
15
16
|
@options[:entry_date] ||= Date.today.to_s
|
16
17
|
@options[:entry_revenue] ||= 0.0
|
@@ -21,6 +22,7 @@ module TheFox::Wallet
|
|
21
22
|
@options[:is_export] ||= false
|
22
23
|
@options[:path] ||= nil
|
23
24
|
@options[:is_interactively] ||= false
|
25
|
+
@options[:force] ||= false
|
24
26
|
end
|
25
27
|
|
26
28
|
def run
|
data/lib/wallet/command_add.rb
CHANGED
@@ -52,6 +52,7 @@ module TheFox::Wallet
|
|
52
52
|
raise "Option --title is required for command '#{NAME}'"
|
53
53
|
end
|
54
54
|
|
55
|
+
puts "id: '#{@options[:entry_id]}'"
|
55
56
|
puts "title: '#{@options[:entry_title]}'"
|
56
57
|
puts "date: " + Date.parse(@options[:entry_date]).to_s
|
57
58
|
puts "revenue: " + NUMBER_FORMAT % @options[:entry_revenue]
|
@@ -59,10 +60,13 @@ module TheFox::Wallet
|
|
59
60
|
puts "balance: " + NUMBER_FORMAT % [@options[:entry_revenue] + @options[:entry_expense]]
|
60
61
|
puts "category: #{@options[:entry_category]}"
|
61
62
|
puts "comment: '#{@options[:entry_comment]}'"
|
63
|
+
puts "force: #{@options[:force] ? 'YES' : 'NO'}"
|
62
64
|
|
63
|
-
entry = Entry.new(@options[:entry_title], @options[:entry_date], @options[:entry_revenue], @options[:entry_expense], @options[:entry_category], @options[:entry_comment])
|
65
|
+
entry = Entry.new(@options[:entry_id], @options[:entry_title], @options[:entry_date], @options[:entry_revenue], @options[:entry_expense], @options[:entry_category], @options[:entry_comment])
|
64
66
|
wallet = Wallet.new(@options[:wallet_path])
|
65
|
-
wallet.add(entry)
|
67
|
+
added = wallet.add(entry, !@options[:force])
|
68
|
+
|
69
|
+
puts "added: #{added ? 'YES' : 'NO'}"
|
66
70
|
end
|
67
71
|
|
68
72
|
def revenue(revenue_s)
|
data/lib/wallet/command_list.rb
CHANGED
@@ -118,7 +118,7 @@ module TheFox::Wallet
|
|
118
118
|
balance_total += entry['balance']
|
119
119
|
|
120
120
|
category = entry['category'] == 'default' ? '' : entry['category']
|
121
|
-
has_category = category != ''
|
121
|
+
# has_category = category != ''
|
122
122
|
|
123
123
|
comment = entry['comment']
|
124
124
|
comment = comment[0, 22] + '...' if comment.length >= 25
|
data/lib/wallet/entry.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
|
2
|
+
require 'uuid'
|
3
|
+
|
2
4
|
module TheFox
|
3
5
|
module Wallet
|
4
6
|
|
5
7
|
class Entry
|
6
8
|
|
9
|
+
attr_reader :id
|
7
10
|
attr_reader :title
|
8
11
|
attr_reader :date
|
9
12
|
attr_reader :revenue
|
@@ -12,10 +15,17 @@ module TheFox
|
|
12
15
|
attr_reader :category
|
13
16
|
attr_reader :comment
|
14
17
|
|
15
|
-
def initialize(title =
|
16
|
-
|
17
|
-
|
18
|
+
def initialize(id = nil, title = nil, date = nil, revenue = nil, expense = nil, category = nil, comment = nil)
|
19
|
+
if !id
|
20
|
+
uuid = UUID.new
|
21
|
+
id = uuid.generate
|
22
|
+
end
|
23
|
+
date ||= Date.today
|
24
|
+
revenue ||= 0.0
|
25
|
+
expense ||= 0.0
|
26
|
+
category ||= 'default'
|
18
27
|
|
28
|
+
self.id = id
|
19
29
|
self.title = title
|
20
30
|
self.date = date
|
21
31
|
|
@@ -23,6 +33,8 @@ module TheFox
|
|
23
33
|
@expense = 0.0
|
24
34
|
@balance = 0.0
|
25
35
|
|
36
|
+
revenue_t = revenue.to_f
|
37
|
+
expense_t = expense.to_f
|
26
38
|
if revenue_t < 0 && expense_t == 0
|
27
39
|
self.revenue = 0.0
|
28
40
|
self.expense = revenue_t
|
@@ -35,12 +47,17 @@ module TheFox
|
|
35
47
|
self.comment = comment
|
36
48
|
end
|
37
49
|
|
50
|
+
def id=(id)
|
51
|
+
@id = id
|
52
|
+
end
|
53
|
+
|
38
54
|
def title=(title)
|
39
55
|
@title = title.to_s
|
40
56
|
end
|
41
57
|
|
42
58
|
def date=(date)
|
43
59
|
if date.is_a?(String)
|
60
|
+
# puts "date parse: '#{date}'"
|
44
61
|
@date = Date.parse(date)
|
45
62
|
elsif date.is_a?(Date)
|
46
63
|
@date = date
|
@@ -57,7 +74,7 @@ module TheFox
|
|
57
74
|
end
|
58
75
|
|
59
76
|
@revenue = revenue_t
|
60
|
-
calc_balance
|
77
|
+
calc_balance
|
61
78
|
end
|
62
79
|
|
63
80
|
def expense=(expense)
|
@@ -68,7 +85,7 @@ module TheFox
|
|
68
85
|
end
|
69
86
|
|
70
87
|
@expense = expense_t
|
71
|
-
calc_balance
|
88
|
+
calc_balance
|
72
89
|
end
|
73
90
|
|
74
91
|
def category=(category)
|
@@ -81,6 +98,7 @@ module TheFox
|
|
81
98
|
|
82
99
|
def to_h
|
83
100
|
{
|
101
|
+
'id' => @id,
|
84
102
|
'title' => @title,
|
85
103
|
'date' => @date.to_s,
|
86
104
|
'revenue' => @revenue,
|
@@ -91,11 +109,25 @@ module TheFox
|
|
91
109
|
}
|
92
110
|
end
|
93
111
|
|
112
|
+
def self.from_h(h)
|
113
|
+
id = h['id']
|
114
|
+
title = h['title']
|
115
|
+
date = h['date']
|
116
|
+
revenue = h['revenue']
|
117
|
+
expense = h['expense']
|
118
|
+
# balance = h['balance']
|
119
|
+
category = h['category']
|
120
|
+
comment = h['comment']
|
121
|
+
|
122
|
+
self.new(id, title, date, revenue, expense, category, comment)
|
123
|
+
end
|
124
|
+
|
94
125
|
private
|
95
126
|
|
96
127
|
def calc_balance
|
97
128
|
@balance = (@revenue.round(NUMBER_ROUND) + @expense.round(NUMBER_ROUND)).to_f.round(NUMBER_ROUND)
|
98
129
|
end
|
130
|
+
|
99
131
|
end
|
100
132
|
|
101
133
|
end
|
data/lib/wallet/version.rb
CHANGED
data/lib/wallet/wallet.rb
CHANGED
@@ -4,7 +4,8 @@
|
|
4
4
|
require 'yaml'
|
5
5
|
require 'yaml/store'
|
6
6
|
require 'csv'
|
7
|
-
require 'ostruct'
|
7
|
+
# require 'ostruct'
|
8
|
+
# require 'pp'
|
8
9
|
|
9
10
|
|
10
11
|
module TheFox
|
@@ -24,6 +25,8 @@ module TheFox
|
|
24
25
|
@has_transaction = false
|
25
26
|
@transaction_files = {}
|
26
27
|
|
28
|
+
@entries_by_ids = nil
|
29
|
+
|
27
30
|
Signal.trap('SIGINT') do
|
28
31
|
puts
|
29
32
|
puts 'received SIGINT. break ...'
|
@@ -31,11 +34,19 @@ module TheFox
|
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
34
|
-
def add(entry)
|
35
|
-
if !entry.is_a?
|
37
|
+
def add(entry, is_unique = false)
|
38
|
+
if !entry.is_a?(Entry)
|
36
39
|
raise ArgumentError, 'variable must be a Entry instance'
|
37
40
|
end
|
38
41
|
|
42
|
+
# puts "add, id #{entry.id}"
|
43
|
+
# puts "add, is_unique #{is_unique}"
|
44
|
+
# puts "add, entry_exist? #{entry_exist?(entry)}"
|
45
|
+
# puts
|
46
|
+
if is_unique && entry_exist?(entry)
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
39
50
|
date = entry.date
|
40
51
|
date_s = date.to_s
|
41
52
|
dbfile_basename = 'month_' + date.strftime('%Y_%m') + '.yml'
|
@@ -56,10 +67,10 @@ module TheFox
|
|
56
67
|
# puts
|
57
68
|
|
58
69
|
if @has_transaction
|
59
|
-
if @transaction_files.has_key?
|
70
|
+
if @transaction_files.has_key?(dbfile_basename)
|
60
71
|
file = @transaction_files[dbfile_basename]['file']
|
61
72
|
else
|
62
|
-
if File.exist?
|
73
|
+
if File.exist?(dbfile_path)
|
63
74
|
file = YAML.load_file(dbfile_path)
|
64
75
|
file['meta']['updated_at'] = DateTime.now.to_s
|
65
76
|
end
|
@@ -72,65 +83,74 @@ module TheFox
|
|
72
83
|
}
|
73
84
|
end
|
74
85
|
|
75
|
-
if !file['days'].has_key?
|
86
|
+
if !file['days'].has_key?(date_s)
|
76
87
|
file['days'][date_s] = []
|
77
88
|
end
|
78
89
|
|
79
|
-
file['days'][date_s].push
|
90
|
+
file['days'][date_s].push(entry.to_h)
|
80
91
|
|
81
92
|
@transaction_files[dbfile_basename]['file'] = file
|
82
93
|
else
|
83
|
-
create_dirs
|
94
|
+
create_dirs
|
84
95
|
|
85
|
-
if File.exist?
|
96
|
+
if File.exist?(dbfile_path)
|
86
97
|
file = YAML.load_file(dbfile_path)
|
87
98
|
file['meta']['updated_at'] = DateTime.now.to_s
|
88
99
|
end
|
89
100
|
|
90
|
-
if !file['days'].has_key?
|
101
|
+
if !file['days'].has_key?(date_s)
|
91
102
|
file['days'][date_s] = []
|
92
103
|
end
|
93
104
|
|
94
|
-
file['days'][date_s].push
|
105
|
+
file['days'][date_s].push(entry.to_h)
|
95
106
|
|
96
|
-
store = YAML::Store.new
|
107
|
+
store = YAML::Store.new(tmpfile_path)
|
97
108
|
store.transaction do
|
98
109
|
store['meta'] = file['meta']
|
99
110
|
store['days'] = file['days']
|
100
111
|
end
|
101
112
|
|
102
|
-
if File.exist?
|
103
|
-
File.rename
|
113
|
+
if File.exist?(tmpfile_path)
|
114
|
+
File.rename(tmpfile_path, dbfile_path)
|
104
115
|
end
|
105
116
|
end
|
117
|
+
|
118
|
+
if @entries_by_ids.nil?
|
119
|
+
@entries_by_ids = {}
|
120
|
+
end
|
121
|
+
@entries_by_ids[entry.id] = entry
|
122
|
+
|
123
|
+
true
|
106
124
|
end
|
107
125
|
|
108
126
|
def transaction_start
|
109
127
|
@has_transaction = true
|
110
128
|
@transaction_files = {}
|
111
129
|
|
112
|
-
create_dirs
|
130
|
+
create_dirs
|
113
131
|
end
|
114
132
|
|
115
133
|
def transaction_end
|
116
134
|
catch(:done) do
|
117
135
|
@transaction_files.each do |tr_file_key, tr_file_data|
|
118
|
-
|
136
|
+
if @exit
|
137
|
+
throw :done
|
138
|
+
end
|
119
139
|
# puts 'keys left: ' + @transaction_files.keys.count.to_s
|
120
140
|
# puts 'tr_file_key: ' + tr_file_key
|
121
141
|
# puts 'path: ' + tr_file_data['path']
|
122
142
|
# puts 'tmp_path: ' + tr_file_data['tmp_path']
|
123
143
|
# puts
|
124
144
|
|
125
|
-
store = YAML::Store.new
|
145
|
+
store = YAML::Store.new(tr_file_data['tmp_path'])
|
126
146
|
store.transaction do
|
127
147
|
store['meta'] = tr_file_data['file']['meta']
|
128
148
|
store['days'] = tr_file_data['file']['days']
|
129
149
|
end
|
130
|
-
@transaction_files.delete
|
150
|
+
@transaction_files.delete(tr_file_key)
|
131
151
|
|
132
|
-
if File.exist?
|
133
|
-
File.rename
|
152
|
+
if File.exist?(tr_file_data['tmp_path'])
|
153
|
+
File.rename(tr_file_data['tmp_path'], tr_file_data['path'])
|
134
154
|
end
|
135
155
|
end
|
136
156
|
end
|
@@ -199,7 +219,6 @@ module TheFox
|
|
199
219
|
end
|
200
220
|
|
201
221
|
def entries(begin_date, category = nil)
|
202
|
-
#def entries(year = nil, month = nil, day = nil, category = nil)
|
203
222
|
begin_year, begin_month, begin_day = begin_date.split('-').map{ |n| n.to_i }
|
204
223
|
|
205
224
|
begin_year_s = begin_year.to_i.to_s
|
@@ -287,7 +306,7 @@ module TheFox
|
|
287
306
|
end
|
288
307
|
|
289
308
|
def gen_html
|
290
|
-
create_dirs
|
309
|
+
create_dirs
|
291
310
|
|
292
311
|
html_options_path = "#{@html_path}/options.yml"
|
293
312
|
html_options = {
|
@@ -298,8 +317,8 @@ module TheFox
|
|
298
317
|
},
|
299
318
|
'changes' => {},
|
300
319
|
}
|
301
|
-
if Dir.exist?
|
302
|
-
if File.exist?
|
320
|
+
if Dir.exist?(@html_path)
|
321
|
+
if File.exist?(html_options_path)
|
303
322
|
html_options = YAML.load_file(html_options_path)
|
304
323
|
html_options['meta']['updated_at'] = DateTime.now.to_s
|
305
324
|
end
|
@@ -416,7 +435,7 @@ module TheFox
|
|
416
435
|
data = YAML.load_file(file_path)
|
417
436
|
|
418
437
|
generate_html = false
|
419
|
-
if html_options['changes'].has_key?
|
438
|
+
if html_options['changes'].has_key?(file_name)
|
420
439
|
if html_options['changes'][file_name]['updated_at'] != data['meta']['updated_at']
|
421
440
|
html_options['changes'][file_name]['updated_at'] = data['meta']['updated_at']
|
422
441
|
generate_html = true
|
@@ -683,14 +702,16 @@ module TheFox
|
|
683
702
|
')
|
684
703
|
index_file.close
|
685
704
|
|
686
|
-
store = YAML::Store.new
|
705
|
+
store = YAML::Store.new(html_options_path)
|
687
706
|
store.transaction do
|
688
707
|
store['meta'] = html_options['meta']
|
689
708
|
store['changes'] = html_options['changes']
|
690
709
|
end
|
691
710
|
|
692
711
|
totaldat_file_c = years_total.map{ |k, y| "#{y.year} #{y.revenue} #{y.expense} #{y.balance} #{y.balance_total}" }
|
693
|
-
|
712
|
+
if totaldat_file_c.count > 6
|
713
|
+
totaldat_file_c = totaldat_file_c.slice(-6, 6)
|
714
|
+
end
|
694
715
|
totaldat_file_c = totaldat_file_c.join("\n")
|
695
716
|
|
696
717
|
totaldat_file_path = "#{@tmp_path}/total.dat"
|
@@ -724,86 +745,118 @@ module TheFox
|
|
724
745
|
end
|
725
746
|
|
726
747
|
def import_csv_file(file_path)
|
727
|
-
transaction_start
|
748
|
+
transaction_start
|
749
|
+
|
750
|
+
row_n = 0
|
751
|
+
csv_options = {
|
752
|
+
:col_sep => ',',
|
753
|
+
#:row_sep => "\n",
|
754
|
+
:headers => true,
|
755
|
+
:return_headers => false,
|
756
|
+
:skip_blanks => true,
|
757
|
+
# :encoding => 'UTF-8',
|
758
|
+
}
|
759
|
+
CSV.foreach(file_path, csv_options) do |row|
|
760
|
+
if @exit
|
761
|
+
break
|
762
|
+
end
|
763
|
+
row_n += 1
|
764
|
+
|
765
|
+
id = row.field('id')
|
766
|
+
date = row.field('date')
|
767
|
+
title = row.field('title')
|
768
|
+
revenue = row.field('revenue')
|
769
|
+
expense = row.field('expense')
|
770
|
+
# balance = row.field('balance')
|
771
|
+
category = row.field('category')
|
772
|
+
comment = row.field('comment')
|
773
|
+
|
774
|
+
added = add(Entry.new(id, title, date, revenue, expense, category, comment), true)
|
775
|
+
|
776
|
+
puts "import row '#{id}' -- #{added ? 'YES' : 'NO'}"
|
777
|
+
end
|
728
778
|
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
779
|
+
puts
|
780
|
+
puts 'save data ...'
|
781
|
+
|
782
|
+
transaction_end
|
783
|
+
end
|
784
|
+
|
785
|
+
def export_csv_file(file_path)
|
786
|
+
csv_options = {
|
787
|
+
:col_sep => ',',
|
788
|
+
:row_sep => "\n",
|
789
|
+
:headers => [
|
790
|
+
'id', 'date', 'title', 'revenue', 'expense', 'balance', 'category', 'comment',
|
791
|
+
],
|
792
|
+
:write_headers => true,
|
793
|
+
# :encoding => 'ISO-8859-1',
|
794
|
+
}
|
795
|
+
CSV.open(file_path, 'wb', csv_options) do |csv|
|
796
|
+
Dir[@data_path + '/month_*.yml'].each do |yaml_file_path|
|
797
|
+
puts 'export ' + File.basename(yaml_file_path)
|
741
798
|
|
742
|
-
|
799
|
+
data = YAML.load_file(yaml_file_path)
|
743
800
|
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
801
|
+
data['days'].each do |day_name, day_items|
|
802
|
+
day_items.each do |entry|
|
803
|
+
csv << [
|
804
|
+
entry['id'],
|
805
|
+
entry['date'],
|
806
|
+
entry['title'],
|
807
|
+
::TheFox::Wallet::NUMBER_FORMAT % entry['revenue'],
|
808
|
+
::TheFox::Wallet::NUMBER_FORMAT % entry['expense'],
|
809
|
+
::TheFox::Wallet::NUMBER_FORMAT % entry['balance'],
|
810
|
+
entry['category'],
|
811
|
+
entry['comment'],
|
812
|
+
]
|
752
813
|
end
|
753
814
|
end
|
754
|
-
|
755
|
-
add Entry.new(title, date, revenue, expense, category, comment)
|
756
|
-
|
757
815
|
end
|
758
|
-
|
759
|
-
puts
|
760
|
-
puts 'save data ...'
|
761
816
|
end
|
762
|
-
|
763
|
-
transaction_end()
|
764
817
|
end
|
765
818
|
|
766
|
-
def
|
767
|
-
|
768
|
-
|
819
|
+
def entry_exist?(entry)
|
820
|
+
if !entry.is_a?(Entry)
|
821
|
+
raise ArgumentError, 'variable must be a Entry instance'
|
822
|
+
end
|
769
823
|
|
770
|
-
|
771
|
-
|
824
|
+
!find_entry_by_id(entry.id).nil?
|
825
|
+
end
|
826
|
+
|
827
|
+
def find_entry_by_id(id)
|
828
|
+
if @entries_by_ids.nil?
|
829
|
+
glob = File.expand_path('month_*.yml', @data_path)
|
772
830
|
|
773
|
-
|
831
|
+
@entries_by_ids = Dir[glob].map { |file_path|
|
832
|
+
data = YAML.load_file(file_path)
|
833
|
+
data['days'].map{ |day_name, day_items|
|
834
|
+
day_items.map{ |entry|
|
835
|
+
Entry.from_h(entry)
|
836
|
+
}
|
837
|
+
}
|
838
|
+
}.flatten.map{ |entry|
|
839
|
+
[entry.id, entry]
|
840
|
+
}.to_h
|
774
841
|
|
775
|
-
|
776
|
-
day_items.each do |entry|
|
777
|
-
out = [
|
778
|
-
entry['date'],
|
779
|
-
'"'+entry['title']+'"',
|
780
|
-
::TheFox::Wallet::NUMBER_FORMAT % entry['revenue'],
|
781
|
-
::TheFox::Wallet::NUMBER_FORMAT % entry['expense'],
|
782
|
-
::TheFox::Wallet::NUMBER_FORMAT % entry['balance'],
|
783
|
-
'"'+entry['category']+'"',
|
784
|
-
'"'+entry['comment']+'"',
|
785
|
-
].join(',')
|
786
|
-
|
787
|
-
csv_file.puts out
|
788
|
-
end
|
789
|
-
end
|
842
|
+
# pp @entries_by_ids
|
790
843
|
end
|
791
844
|
|
792
|
-
|
845
|
+
@entries_by_ids[id]
|
793
846
|
end
|
794
847
|
|
795
848
|
private
|
796
849
|
|
797
850
|
def create_dirs
|
798
|
-
if !Dir.exist?
|
851
|
+
if !Dir.exist?(@dir_path)
|
799
852
|
Dir.mkdir(@dir_path)
|
800
853
|
end
|
801
854
|
|
802
|
-
if !Dir.exist?
|
855
|
+
if !Dir.exist?(@data_path)
|
803
856
|
Dir.mkdir(@data_path)
|
804
857
|
end
|
805
858
|
|
806
|
-
if !Dir.exist?
|
859
|
+
if !Dir.exist?(@tmp_path)
|
807
860
|
Dir.mkdir(@tmp_path)
|
808
861
|
end
|
809
862
|
|
@@ -815,14 +868,14 @@ module TheFox
|
|
815
868
|
end
|
816
869
|
end
|
817
870
|
|
818
|
-
def calc_day(
|
871
|
+
def calc_day(day, category = nil)
|
819
872
|
revenue = 0
|
820
873
|
expense = 0
|
821
874
|
balance = 0
|
822
875
|
if category
|
823
876
|
category.to_s.downcase!
|
824
877
|
|
825
|
-
|
878
|
+
day.each do |entry|
|
826
879
|
if entry['category'] == category
|
827
880
|
revenue += entry['revenue']
|
828
881
|
expense += entry['expense']
|
@@ -830,7 +883,7 @@ module TheFox
|
|
830
883
|
end
|
831
884
|
end
|
832
885
|
else
|
833
|
-
|
886
|
+
day.each do |entry|
|
834
887
|
revenue += entry['revenue']
|
835
888
|
expense += entry['expense']
|
836
889
|
balance += entry['balance']
|
data/tests/tc_command_add.rb
CHANGED
@@ -5,8 +5,11 @@ require 'wallet'
|
|
5
5
|
|
6
6
|
|
7
7
|
class TestAddCommand < MiniTest::Test
|
8
|
+
|
9
|
+
include TheFox::Wallet
|
10
|
+
|
8
11
|
def test_revenue
|
9
|
-
cmd =
|
12
|
+
cmd = AddCommand.new
|
10
13
|
|
11
14
|
# String
|
12
15
|
assert_equal(nil, cmd.revenue(nil))
|
@@ -32,7 +35,7 @@ class TestAddCommand < MiniTest::Test
|
|
32
35
|
end
|
33
36
|
|
34
37
|
def test_expense
|
35
|
-
cmd =
|
38
|
+
cmd = AddCommand.new
|
36
39
|
|
37
40
|
# String
|
38
41
|
assert_equal(nil, cmd.expense(nil))
|
data/tests/tc_entry.rb
CHANGED
@@ -5,14 +5,17 @@ require 'wallet'
|
|
5
5
|
|
6
6
|
|
7
7
|
class TestEntry < MiniTest::Test
|
8
|
+
|
9
|
+
include TheFox::Wallet
|
10
|
+
|
8
11
|
def test_base
|
9
|
-
entry =
|
12
|
+
entry = Entry.new
|
10
13
|
|
11
14
|
assert_equal('TheFox::Wallet::Entry', entry.class.to_s)
|
12
15
|
end
|
13
16
|
|
14
17
|
def test_set_title
|
15
|
-
entry =
|
18
|
+
entry = Entry.new(nil, 'test1')
|
16
19
|
assert_equal('test1', entry.title)
|
17
20
|
|
18
21
|
entry.title = 'test2'
|
@@ -22,27 +25,27 @@ class TestEntry < MiniTest::Test
|
|
22
25
|
def test_set_date
|
23
26
|
now = Date.today
|
24
27
|
|
25
|
-
entry =
|
28
|
+
entry = Entry.new
|
26
29
|
assert_equal('Date', entry.date.class.to_s)
|
27
30
|
assert_equal(now.to_s, entry.date.to_s)
|
28
31
|
|
29
|
-
entry =
|
32
|
+
entry = Entry.new(nil, 'test', '2015-02-21')
|
30
33
|
assert_equal('Date', entry.date.class.to_s)
|
31
34
|
assert_equal('2015-02-21', entry.date.to_s)
|
32
35
|
|
33
36
|
entry.date = '2015-01-01'
|
34
37
|
assert_equal('2015-01-01', entry.date.to_s)
|
35
38
|
|
36
|
-
entry =
|
39
|
+
entry = Entry.new(nil, 'test', '2014-2-21')
|
37
40
|
assert_equal('2014-02-21', entry.date.to_s)
|
38
41
|
|
39
42
|
entry.date = '2013-1-1'
|
40
43
|
assert_equal('2013-01-01', entry.date.to_s)
|
41
44
|
|
42
|
-
entry =
|
45
|
+
entry = Entry.new(nil, 'test', Date.parse('2015-01-02'))
|
43
46
|
assert_equal('2015-01-02', entry.date.to_s)
|
44
47
|
|
45
|
-
entry =
|
48
|
+
entry = Entry.new
|
46
49
|
entry.date = Date.today
|
47
50
|
assert_equal(now.to_s, entry.date.to_s)
|
48
51
|
|
@@ -51,16 +54,16 @@ class TestEntry < MiniTest::Test
|
|
51
54
|
end
|
52
55
|
|
53
56
|
def test_set_revenue_expense
|
54
|
-
entry =
|
57
|
+
entry = Entry.new
|
55
58
|
assert_equal(0, entry.revenue)
|
56
59
|
assert_equal(0, entry.expense)
|
57
60
|
|
58
|
-
entry =
|
61
|
+
entry = Entry.new(nil, 'test', '2015-02-21', 20)
|
59
62
|
assert_equal(20, entry.revenue)
|
60
63
|
assert_equal(0, entry.expense)
|
61
64
|
assert_equal(20, entry.balance)
|
62
65
|
|
63
|
-
entry =
|
66
|
+
entry = Entry.new(nil, 'test', '2015-02-21', '20', '-21')
|
64
67
|
assert_equal(20, entry.revenue)
|
65
68
|
assert_equal(-21, entry.expense)
|
66
69
|
assert_equal(-1, entry.balance)
|
@@ -83,12 +86,12 @@ class TestEntry < MiniTest::Test
|
|
83
86
|
assert_equal(-2.02, entry.expense)
|
84
87
|
assert_equal(-1.02, entry.balance)
|
85
88
|
|
86
|
-
entry =
|
89
|
+
entry = Entry.new(nil, 'test', '2015-02-21', -42)
|
87
90
|
assert_equal(0, entry.revenue)
|
88
91
|
assert_equal(-42, entry.expense)
|
89
92
|
assert_equal(-42, entry.balance)
|
90
93
|
|
91
|
-
entry =
|
94
|
+
entry = Entry.new(nil, 'test', '2015-02-21', -30.03)
|
92
95
|
assert_equal(0, entry.revenue)
|
93
96
|
assert_equal(-30.03, entry.expense)
|
94
97
|
assert_equal(-30.03, entry.balance)
|
@@ -104,7 +107,7 @@ class TestEntry < MiniTest::Test
|
|
104
107
|
end
|
105
108
|
|
106
109
|
def test_set_category
|
107
|
-
entry =
|
110
|
+
entry = Entry.new(nil, 'test', '2015-02-21', 20, 0, 'c1')
|
108
111
|
assert_equal('c1', entry.category)
|
109
112
|
|
110
113
|
entry.category = 'c2'
|
@@ -115,7 +118,7 @@ class TestEntry < MiniTest::Test
|
|
115
118
|
end
|
116
119
|
|
117
120
|
def test_set_comment
|
118
|
-
entry =
|
121
|
+
entry = Entry.new(nil, 'test', '2015-02-21', 20, 0, 'c1', 'co1')
|
119
122
|
assert_equal('co1', entry.comment)
|
120
123
|
|
121
124
|
entry.comment = 'co2'
|
@@ -126,7 +129,7 @@ class TestEntry < MiniTest::Test
|
|
126
129
|
end
|
127
130
|
|
128
131
|
def test_to_hash
|
129
|
-
entry =
|
132
|
+
entry = Entry.new(nil, 'test', '2015-02-21', 20, -12.34, 'c3')
|
130
133
|
|
131
134
|
assert_equal('2015-02-21', entry.to_h['date'].to_s)
|
132
135
|
assert_equal(20, entry.to_h['revenue'])
|
data/tests/tc_wallet.rb
CHANGED
@@ -1,36 +1,40 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'minitest/autorun'
|
4
|
+
require 'fileutils'
|
4
5
|
require 'wallet'
|
5
6
|
|
6
7
|
|
7
8
|
class TestWallet < MiniTest::Test
|
9
|
+
|
10
|
+
include TheFox::Wallet
|
11
|
+
|
8
12
|
def test_that_it_has_a_version_number
|
9
|
-
refute_nil
|
13
|
+
refute_nil(::TheFox::Wallet::VERSION)
|
10
14
|
end
|
11
15
|
|
12
16
|
def test_base
|
13
|
-
wallet =
|
17
|
+
wallet = Wallet.new('wallet_test')
|
14
18
|
|
15
19
|
assert_equal('TheFox::Wallet::Wallet', wallet.class.to_s)
|
16
20
|
assert_equal(true, !Dir.exist?('wallet_test'))
|
17
21
|
end
|
18
22
|
|
19
|
-
def
|
20
|
-
wallet =
|
21
|
-
|
22
|
-
wallet.add
|
23
|
-
wallet.add
|
24
|
-
wallet.add
|
25
|
-
wallet.add
|
26
|
-
wallet.add
|
27
|
-
wallet.add
|
28
|
-
wallet.add
|
29
|
-
wallet.add
|
30
|
-
wallet.add
|
31
|
-
wallet.add
|
32
|
-
|
33
|
-
sum = wallet.sum
|
23
|
+
def test_add1
|
24
|
+
wallet = Wallet.new('wallet_test')
|
25
|
+
|
26
|
+
wallet.add(Entry.new(nil, 'test', '2014-01-01', 100))
|
27
|
+
wallet.add(Entry.new(nil, 'test', '2014-01-01', 50))
|
28
|
+
wallet.add(Entry.new(nil, 'test', '2014-01-01', -10))
|
29
|
+
wallet.add(Entry.new(nil, 'test', '2014-01-02', -10))
|
30
|
+
wallet.add(Entry.new(nil, 'test', '2015-01-01', 100, 0, 'c1'))
|
31
|
+
wallet.add(Entry.new(nil, 'test', '2015-01-02', 0, -10, 'c2'))
|
32
|
+
wallet.add(Entry.new(nil, 'test', '2015-02-21', 20))
|
33
|
+
wallet.add(Entry.new(nil, 'test', '2015-02-21', 0, -5, 'c1'))
|
34
|
+
wallet.add(Entry.new(nil, 'test', '2015-02-21', 0, -1.5, 'c2'))
|
35
|
+
wallet.add(Entry.new(nil, 'test', '2015-02-22', 10))
|
36
|
+
|
37
|
+
sum = wallet.sum
|
34
38
|
assert_equal(280, sum[:revenue])
|
35
39
|
assert_equal(-36.5, sum[:expense])
|
36
40
|
assert_equal(243.5, sum[:balance])
|
@@ -176,23 +180,57 @@ class TestWallet < MiniTest::Test
|
|
176
180
|
assert_equal(-1.5, sum[:balance])
|
177
181
|
|
178
182
|
assert_equal(['default', 'c1', 'c2'], wallet.categories)
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_add2
|
186
|
+
wallet = Wallet.new('wallet_test')
|
179
187
|
|
180
|
-
assert_equal(true,
|
181
|
-
assert_equal(true,
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
Dir.unlink 'wallet_test/tmp'
|
190
|
-
Dir.unlink 'wallet_test'
|
188
|
+
assert_equal(true, wallet.add(Entry.new(nil, 'test', '2014-01-01', 1)))
|
189
|
+
assert_equal(true, wallet.add(Entry.new(nil, 'test', '2014-01-01', 1), true))
|
190
|
+
|
191
|
+
assert_equal(true, wallet.add(Entry.new(1, 'test', '2014-01-01', 1), true))
|
192
|
+
assert_equal(false, wallet.add(Entry.new(1, 'test', '2014-01-01', 1), true))
|
193
|
+
|
194
|
+
assert_equal(true, wallet.add(Entry.new('my_id', 'test', '2014-01-01', 1), true))
|
195
|
+
assert_equal(false, wallet.add(Entry.new('my_id', 'test', '2014-01-01', 1), true))
|
196
|
+
assert_equal(true, wallet.add(Entry.new('my_id', 'test', '2014-01-01', 1), false))
|
191
197
|
end
|
192
198
|
|
193
199
|
def test_exceptions
|
194
|
-
wallet =
|
200
|
+
wallet = Wallet.new('wallet_test')
|
201
|
+
|
202
|
+
assert_raises(ArgumentError) do
|
203
|
+
wallet.add(12)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_find_entry_by_id
|
208
|
+
wallet = Wallet.new('wallet_test')
|
209
|
+
|
210
|
+
wallet.add(Entry.new(nil, 'test', '2014-01-01', -1))
|
211
|
+
wallet.add(Entry.new(1, 'test', '2014-01-01', 1))
|
212
|
+
wallet.add(Entry.new(2, 'test', '2014-01-02', 2))
|
213
|
+
wallet.add(Entry.new(3, 'test', '2015-03-04', 3))
|
214
|
+
|
215
|
+
found_entry = wallet.find_entry_by_id(1)
|
216
|
+
assert_instance_of(Entry, found_entry)
|
217
|
+
assert_equal(1, found_entry.id)
|
218
|
+
|
219
|
+
found_entry = wallet.find_entry_by_id(2)
|
220
|
+
assert_instance_of(Entry, found_entry)
|
221
|
+
assert_equal(2, found_entry.id)
|
195
222
|
|
196
|
-
|
223
|
+
found_entry = wallet.find_entry_by_id(3)
|
224
|
+
assert_instance_of(Entry, found_entry)
|
225
|
+
assert_equal(3, found_entry.id)
|
226
|
+
|
227
|
+
assert_nil(wallet.find_entry_by_id(4))
|
228
|
+
assert_nil(wallet.find_entry_by_id(5))
|
229
|
+
assert_nil(wallet.find_entry_by_id(6))
|
230
|
+
end
|
231
|
+
|
232
|
+
def teardown
|
233
|
+
FileUtils.rm_r('wallet_test', {:force => true})
|
197
234
|
end
|
235
|
+
|
198
236
|
end
|
data/thefox-wallet.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thefox-wallet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Mayer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: uuid
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.3'
|
27
41
|
description: A Ruby library for tracking your finances.
|
28
42
|
email: christian@fox21.at
|
29
43
|
executables:
|
@@ -31,12 +45,14 @@ executables:
|
|
31
45
|
extensions: []
|
32
46
|
extra_rdoc_files: []
|
33
47
|
files:
|
48
|
+
- ".editorconfig"
|
34
49
|
- ".gitignore"
|
35
50
|
- ".travis.yml"
|
36
51
|
- Gemfile
|
37
52
|
- Makefile
|
38
53
|
- Makefile.common
|
39
54
|
- README.md
|
55
|
+
- bin/.gitignore
|
40
56
|
- bin/wallet
|
41
57
|
- lib/wallet.rb
|
42
58
|
- lib/wallet/command.rb
|