thefox-wallet 0.10.2 → 0.11.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/.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
|