moneymanager 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c6ed2a51631e896adc9d37ccd801863666e3daf
4
- data.tar.gz: 90e85ddbf9508dc3b504adac53a1c78f2fbadfeb
3
+ metadata.gz: 39450e9d5be4a772dec12a2db8fb9d0067ead553
4
+ data.tar.gz: 0db1716715290873ac2c5a903ef24a0ca9cef7ef
5
5
  SHA512:
6
- metadata.gz: 0b0d80d711e1f45d17faaf0c7b9ba502cd4b06c7eae31d70720c58ea6efffa5f3a1110b4592c4d4cc87ddbf9477f28d35e2627feb7e94648472449b4a62b2c89
7
- data.tar.gz: bc74ae900f4f5cd0ed978ece2b34f454f09d6aa4e0dbe3b2c95fe9bfc81ecc723497c4a2056b0d30d38d7a83c3595172a7663f28b9bd83ed830b3592e9513796
6
+ metadata.gz: 79a578a780c6c0f523665c2b4da019912cc45588fc9ccaf76abb58e56a146a8998f2d8247b3165c91fc172ef0d19460b844eaf6a1e7faf3298b3f9b6289a9451
7
+ data.tar.gz: 0c3112832a722691da332cd101b5fbe39a721551b2e9135984f39cae1451444f1c21f45f9735eac9b7b889317df84e7beebfe2927d7f924668270704915f47cb
data/README.md CHANGED
@@ -1,34 +1,199 @@
1
1
  # Moneymanager
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/moneymanager`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ This is ruby app I wrote to help me managing my personal finance. Some features are still missing, I'll add in the future.
4
+ I ended up writing my own tool instead of using MoneyWiz et simila is that all the tools I tried are either overcomplicated or dont'have the basic information I need (and also because I like writing Ruby code)
4
5
 
5
- TODO: Delete this and the text above, and describe your gem
6
+ ## Features
6
7
 
7
- ## Installation
8
+ * Import transactions from a `CSV - CAMT` file. I'm not sure about your bank, but SparkasseBerlin has this option.
9
+ * The import process is idempotent. Import same transaction multiple times doesn't get duplicate.
10
+ * Print the list of transacions.
11
+ * Review the transaction and flag all the approved ones.
12
+ * Tag the transaction and assign a tag to each one
13
+ * Print the summary of income/expense general or divided by category.
14
+ * All the actions have an options to consider only a specific month.
8
15
 
9
- Add this line to your application's Gemfile:
16
+ ## Why you shouldn't use this
10
17
 
11
- ```ruby
12
- gem 'moneymanager'
13
- ```
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install moneymanager
18
+ * The database is just a plain, non-encrypted file.
19
+ * There are no fancy charts.
20
+ * The `print/review/tag` taks are _monthly_ based. If you have undreds of transaction per month using this tool can be tedious.
21
+ *
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
25
+ #### Install the gem
26
+
27
+ $ gem install moneymanager
28
+
29
+ #### Import your CSV FILE
30
+
31
+ $ mm add exported.csv
32
+ Parsed: 99
33
+ Skipped: 0
34
+ Inserted: 99
35
+ # If executed twice, the entries are not duplicated
36
+ $ mm add exported.csv
37
+ Parsed: 99
38
+ Skipped: 99
39
+ Inserted: 0
40
+
41
+ #### Print the transactions
42
+ By default all the transactions are printed. A month can be specified with the `--month` parameter
43
+
44
+ $ mm print
45
+ +-----+----------+--------------+----------------------------------------------------+-------------+
46
+ | ✔/✖︎ | Date | Tag | Reason | Amount |
47
+ +-----+----------+--------------+----------------------------------------------------+-------------+
48
+ | ✖︎︎ | 17/08/01 | | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
49
+ | ✖︎ | 17/08/01 | | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
50
+ | ✖︎ | 17/08/01 | | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
51
+ | ✖︎ | 17/08/01 | | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
52
+ | ✖︎ | 17/08/01 | | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
53
+ | ✖︎ | 17/08/02 | | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
54
+ | ✖︎ | 17/08/31 | | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
55
+ +-----+----------+--------------+----------------------------------------------------+-------------+
56
+
57
+
58
+ #### Review and approve the transactions
59
+ Flag all the approved transaction.
60
+
61
+ $ mm review
62
+ +----------+------------------------------------------------------+
63
+ | Date | 2017-08-01 |
64
+ | Reason | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ |
65
+ | Amount | -999.0 € |
66
+ | Company | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ |
67
+ | Approved | ✖ |
68
+ | Tag | |
69
+ +----------+------------------------------------------------------+
70
+ Do you recognize? (Use arrow keys, press Enter to select)
71
+ ‣ yes
72
+ no
73
+ skip
74
+ abort
75
+
76
+
77
+
78
+ #### Tag each transaction
79
+
80
+ Assign a tag to each (or not) transaction. To generate hierarchy of tags, use a `/` like `Car/Insurance`s
81
+
82
+ $ mm tag
83
+ +----------+------------------------------------------------------+
84
+ | Date | 2017-08-01 |
85
+ | Reason | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ |
86
+ | Amount | -99.0 € |
87
+ | Company | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ |
88
+ | Approved | ✔︎ |
89
+ | Tag | |
90
+ +----------+------------------------------------------------------+
91
+ Do you want add a tags? (Use arrow keys, press Enter to select)
92
+ ‣ 1. Skip
93
+ 2. Abort
94
+ 3. Create
95
+ Car/Gasoline
96
+ Car/Insurance
97
+ Car/Tire
98
+ Heating
99
+ Mortage
100
+
101
+
102
+
103
+ #### Enjoi the list of transaction
104
+
105
+ $ mm print
106
+ +-----+----------+------------------------+--------------------------------------------------+-------------+
107
+ | ✔/✖︎ | Date | Tag | Reason | Amount |
108
+ +-----+----------+------------------------+--------------------------------------------------+-------------+
109
+ | ✔︎ | 17/08/01 | ◼◼◼◼◼◼ Censored ◼◼◼◼◼◼ | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
110
+ | ✔︎ | 17/08/01 | ◼◼◼◼◼◼ Censored ◼◼◼◼◼◼ | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
111
+ | ✔︎ | 17/08/01 | ◼◼◼◼◼◼ Censored ◼◼◼◼◼◼ | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
112
+ | ✔︎ | 17/08/31 | ◼◼◼◼◼◼ Censored ◼◼◼◼◼◼ | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
113
+ | ✔︎ | 17/08/31 | ◼◼◼◼◼◼ Censored ◼◼◼◼◼◼ | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
114
+ | ✔︎ | 17/08/31 | ◼◼◼◼◼◼ Censored ◼◼◼◼◼◼ | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
115
+ | ✔︎ | 17/08/31 | ◼◼◼◼◼◼ Censored ◼◼◼◼◼◼ | ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ C E N S O R E D ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼︎ | 99999.99 € |
116
+ +-----+----------+------------------------+--------------------------------------------------+-------------+
117
+
118
+ ## Reporting
119
+
120
+ #### Global Incomes/Expenses
121
+
122
+ $ mm report --month 8
123
+
124
+ $ mm report --month 8
125
+ Which type of report? (Use arrow keys, press Enter to select)
126
+ ‣ Global Incomes/Expenses
127
+ All categories
128
+ One category
129
+
130
+
131
+ +---------+-----------+
132
+ | Summary |
133
+ +---------+-----------+
134
+ | Income | 1234.0 € |
135
+ | Expense | -5678.0 € |
136
+ | Delta | 9999.0 € |
137
+ +---------+-----------+
138
+
139
+ #### Global Incomes/Expenses
140
+
141
+
142
+ $ mm report
143
+ Which type of report? (Use arrow keys, press Enter to select)
144
+ Global Incomes/Expenses
145
+ ‣ All categories
146
+ One category
147
+
148
+
149
+ +------------+----------+
150
+ | Incomes |
151
+ +------------+----------+
152
+ | Salary | 999.0 € |
153
+ | Investment | 999.0 € |
154
+ | Rent | 999.0 € |
155
+ +------------+----------+
156
+ +-------------------+-----------+
157
+ | Expenses |
158
+ +-------------------+-----------+
159
+ | Heating | -99.0 € |
160
+ | Mortage | -99.0 € |
161
+ | Car/Gasoline | -99.0 € |
162
+ | Car/Insurace | -9999.0 € |
163
+ | Car/Tire | -999.0 € |
164
+ +-------------------+-----------+
165
+
166
+
167
+ #### Report for one Tag
168
+
169
+
170
+ $ mm report
171
+ Which type of report? (Use arrow keys, press Enter to select)
172
+ Global Incomes/Expenses
173
+ All categories
174
+ ‣ One category
175
+
176
+ Select a tag. (Use arrow keys, press Enter to select)
177
+ ‣ Heating
178
+ Mortage
179
+ Car/Gasoline
180
+ Car/Insurance
181
+ Car/Tire
182
+
183
+ +-----------------+---------+
184
+ | Expenses |
185
+ +-----------------+---------+
186
+ | Heating | -99.0 € |
187
+ +-----------------+---------+
188
+
189
+
190
+
191
+
192
+ ## Next release
193
+
194
+ * Report for nested tags ( Car/Gasoline, Car/Insurance etc)
195
+ * Multiple tags
196
+ * Report for one tag splitted by month
32
197
 
33
198
  ## Contributing
34
199
 
data/exe/mm CHANGED
@@ -18,6 +18,16 @@ command :add do |c|
18
18
  end
19
19
  end
20
20
 
21
+ command :reset do |c|
22
+ c.syntax = 'mm reset'
23
+ c.description = 'Delete the current archive (danger zone!)'
24
+ c.action do |_args, _options|
25
+ if agree('Do you really want to delete everything?')
26
+ Moneymanager::Archiver.reset
27
+ end
28
+ end
29
+ end
30
+
21
31
  command :print do |c|
22
32
  c.syntax = 'mm print [--month <month>]'
23
33
  c.description = 'Print the list of transactions'
@@ -48,21 +58,69 @@ command :review do |c|
48
58
  end
49
59
  end
50
60
 
51
- command :summary do |c|
52
- c.syntax = 'mm summary'
53
- c.description = 'Print the sum of the revenue, the sum of the expenses and the differences'
54
- c.option '--month INTEGER', Integer, 'Specify the month to review.'
61
+ command :report do |c|
62
+ c.syntax = 'mm report'
63
+ c.description = 'Print all the revenues and all the expenses grouped by tag'
64
+ c.option '--month INTEGER', Integer, 'Specify the month to report.'
55
65
  c.action do |_args, options|
56
66
  entries = get_entries(options.month)
57
- expenses = entries.reject(&:is_income).map(&:amount).reduce(:+)
58
- incomes = entries.reject(&:is_expense).map(&:amount).reduce(:+)
59
- Layout.print_summary(incomes, expenses)
60
67
 
68
+ prompt = TTY::Prompt.new
69
+ command = prompt.select('Which type of report?') do |menu|
70
+ menu.choice 'Global Incomes/Expenses', :global
71
+ menu.choice 'All categories', :all
72
+ menu.choice 'Specific Tag', :one
73
+ end
74
+
75
+ case command
76
+ when :global
77
+ print_global_report(entries)
78
+ when :all
79
+ print_all_categories_report(entries)
80
+ when :one
81
+ archiver = Moneymanager::Archiver.new
82
+ tags = archiver.tags.sort!
83
+ tag = prompt.select('Select a tag.', tags, per_page: 30)
84
+ print_one_category_report(entries, tag)
85
+ end
61
86
  end
62
87
  end
63
88
 
89
+ def print_global_report(entries)
90
+ expenses = entries.reject(&:income?).map(&:amount).reduce(:+)
91
+ incomes = entries.reject(&:expense?).map(&:amount).reduce(:+)
92
+ Layout.print_summary(incomes, expenses)
93
+ end
94
+
95
+ def print_all_categories_report(entries)
96
+ expenses = entries.reject(&:income?).each_with_object(Hash.new(0)) do |current, sum|
97
+ tag = current.tag ||= 'Unknown'
98
+ sum[tag] += current.amount
99
+ end
100
+ incomes = entries.reject(&:expense?).each_with_object(Hash.new(0)) do |current, sum|
101
+ tag = current.tag ||= 'Unknown'
102
+ sum[tag] += current.amount
103
+ end
104
+
105
+ incomes = incomes.map { |x, v| [x, v] }
106
+ Layout.print_summary_per_category('Incomes', incomes)
107
+
108
+ expenses = expenses.map { |x, v| [x, v] }
109
+ Layout.print_summary_per_category('Expenses', expenses)
110
+ end
111
+
112
+ def print_one_category_report(entries, tag)
113
+ entries = entries.select do |entry|
114
+ entry.tag == tag
115
+ end
116
+ print_all_categories_report(entries)
117
+ end
118
+
64
119
  def get_entries(month)
65
- month ||= Date.today.month
66
120
  archiver = Moneymanager::Archiver.new
67
- archiver.all_entries_per_month(month)
121
+ if month.nil?
122
+ archiver.all_entries
123
+ else
124
+ archiver.all_entries_per_month(month)
125
+ end
68
126
  end
@@ -16,10 +16,10 @@ module Moneymanager
16
16
  end
17
17
 
18
18
  def initialize
19
- @db = if File.exist? Archiver.archive_path
20
- YAML.load_file(Archiver.archive_path)
19
+ if File.exist? Archiver.archive_path
20
+ @db = YAML.load_file(Archiver.archive_path)
21
21
  else
22
- Archiver.empty_archive
22
+ @db = Archiver.empty_archive
23
23
  end
24
24
  end
25
25
 
@@ -59,6 +59,7 @@ module Moneymanager
59
59
  def tags
60
60
  @db[:tags]
61
61
  end
62
+
62
63
  def store_tag(tag)
63
64
  @db[:tags] << tag
64
65
  save
@@ -28,12 +28,12 @@ module Moneymanager
28
28
  amount < 0 ? s.red : s.green
29
29
  end
30
30
 
31
- def is_expense
31
+ def expense?
32
32
  amount < 0
33
33
  end
34
- def is_income
35
- !is_expense
34
+
35
+ def income?
36
+ !expense?
36
37
  end
37
-
38
38
  end
39
39
  end
@@ -24,8 +24,8 @@ class Layout
24
24
  end
25
25
 
26
26
  def self.formatted_amount(amount)
27
- s = amount.to_s + ' €'
28
- amount < 0 ? s.red : s.green
27
+ s = amount.to_s + ' €'
28
+ amount < 0 ? s.red : s.green
29
29
  end
30
30
 
31
31
  def self.print_summary(income, expenses)
@@ -36,7 +36,21 @@ class Layout
36
36
  t << ['Delta', formatted_amount(delta)]
37
37
  end
38
38
  table.align_column(1, :right)
39
- table.title = "Summary"
39
+ table.title = 'Summary'
40
+ puts table
41
+ end
42
+
43
+ def self.print_summary_per_category(title, rows)
44
+ return unless rows.count > 0
45
+ rows = rows.sort! { |r1, r2| r1.first <=> r2.first }
46
+ rows = rows.map do |row|
47
+ row[-1] = formatted_amount(row.last)
48
+ row
49
+ end
50
+ table = Terminal::Table.new rows: rows
51
+ table.align_column(1, :right)
52
+ table.title = title
53
+
40
54
  puts table
41
55
  end
42
56
 
@@ -6,13 +6,11 @@ class Tagger
6
6
  def retag(entries)
7
7
  archiver = Moneymanager::Archiver.new
8
8
 
9
-
10
-
11
9
  prompt = TTY::Prompt.new
12
10
  entries.each do |entry|
13
11
  Layout.clear
14
12
  Layout.print_single(entry)
15
- options = default_options.concat(archiver.tags)
13
+ options = default_options.concat(archiver.tags.sort!)
16
14
  action = prompt.select('Do you want add a tags?', options, per_page: 30)
17
15
 
18
16
  if action == default_options[0]
@@ -1,3 +1,3 @@
1
1
  module Moneymanager
2
- VERSION = '0.1.1'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
data/lib/moneymanager.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'terminal-table'
2
2
  require 'colorize'
3
3
  require 'tty-prompt'
4
- require "moneymanager/version"
4
+ require 'moneymanager/version'
5
5
  require 'moneymanager/archiver'
6
6
  require 'moneymanager/layout'
7
7
  require 'moneymanager/parser'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moneymanager
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ignazioc
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-18 00:00:00.000000000 Z
11
+ date: 2017-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander