moneymanager 0.1.1 → 0.2.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 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