rvgp 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +23 -0
  4. data/LICENSE +504 -0
  5. data/README.md +223 -0
  6. data/Rakefile +32 -0
  7. data/bin/rvgp +8 -0
  8. data/lib/rvgp/application/config.rb +159 -0
  9. data/lib/rvgp/application/descendant_registry.rb +122 -0
  10. data/lib/rvgp/application/status_output.rb +139 -0
  11. data/lib/rvgp/application.rb +170 -0
  12. data/lib/rvgp/base/command.rb +457 -0
  13. data/lib/rvgp/base/grid.rb +531 -0
  14. data/lib/rvgp/base/reader.rb +29 -0
  15. data/lib/rvgp/base/reconciler.rb +434 -0
  16. data/lib/rvgp/base/validation.rb +261 -0
  17. data/lib/rvgp/commands/cashflow.rb +160 -0
  18. data/lib/rvgp/commands/grid.rb +70 -0
  19. data/lib/rvgp/commands/ireconcile.rb +95 -0
  20. data/lib/rvgp/commands/new_project.rb +296 -0
  21. data/lib/rvgp/commands/plot.rb +41 -0
  22. data/lib/rvgp/commands/publish_gsheets.rb +83 -0
  23. data/lib/rvgp/commands/reconcile.rb +58 -0
  24. data/lib/rvgp/commands/rotate_year.rb +202 -0
  25. data/lib/rvgp/commands/validate_journal.rb +59 -0
  26. data/lib/rvgp/commands/validate_system.rb +44 -0
  27. data/lib/rvgp/commands.rb +160 -0
  28. data/lib/rvgp/dashboard.rb +252 -0
  29. data/lib/rvgp/fakers/fake_feed.rb +245 -0
  30. data/lib/rvgp/fakers/fake_journal.rb +57 -0
  31. data/lib/rvgp/fakers/fake_reconciler.rb +88 -0
  32. data/lib/rvgp/fakers/faker_helpers.rb +25 -0
  33. data/lib/rvgp/gem.rb +80 -0
  34. data/lib/rvgp/journal/commodity.rb +453 -0
  35. data/lib/rvgp/journal/complex_commodity.rb +214 -0
  36. data/lib/rvgp/journal/currency.rb +101 -0
  37. data/lib/rvgp/journal/journal.rb +141 -0
  38. data/lib/rvgp/journal/posting.rb +156 -0
  39. data/lib/rvgp/journal/pricer.rb +267 -0
  40. data/lib/rvgp/journal.rb +24 -0
  41. data/lib/rvgp/plot/gnuplot.rb +478 -0
  42. data/lib/rvgp/plot/google-drive/output_csv.rb +44 -0
  43. data/lib/rvgp/plot/google-drive/output_google_sheets.rb +434 -0
  44. data/lib/rvgp/plot/google-drive/sheet.rb +67 -0
  45. data/lib/rvgp/plot.rb +293 -0
  46. data/lib/rvgp/pta/hledger.rb +237 -0
  47. data/lib/rvgp/pta/ledger.rb +308 -0
  48. data/lib/rvgp/pta.rb +311 -0
  49. data/lib/rvgp/reconcilers/csv_reconciler.rb +424 -0
  50. data/lib/rvgp/reconcilers/journal_reconciler.rb +41 -0
  51. data/lib/rvgp/reconcilers/shorthand/finance_gem_hacks.rb +48 -0
  52. data/lib/rvgp/reconcilers/shorthand/international_atm.rb +152 -0
  53. data/lib/rvgp/reconcilers/shorthand/investment.rb +144 -0
  54. data/lib/rvgp/reconcilers/shorthand/mortgage.rb +195 -0
  55. data/lib/rvgp/utilities/grid_query.rb +190 -0
  56. data/lib/rvgp/utilities/yaml.rb +131 -0
  57. data/lib/rvgp/utilities.rb +44 -0
  58. data/lib/rvgp/validations/balance_validation.rb +68 -0
  59. data/lib/rvgp/validations/duplicate_tags_validation.rb +48 -0
  60. data/lib/rvgp/validations/uncategorized_validation.rb +15 -0
  61. data/lib/rvgp.rb +66 -0
  62. data/resources/README.MD/2022-cashflow-google.png +0 -0
  63. data/resources/README.MD/2022-cashflow.png +0 -0
  64. data/resources/README.MD/all-wealth-growth-google.png +0 -0
  65. data/resources/README.MD/all-wealth-growth.png +0 -0
  66. data/resources/gnuplot/default.yml +80 -0
  67. data/resources/i18n/en.yml +192 -0
  68. data/resources/iso-4217-currencies.json +171 -0
  69. data/resources/skel/Rakefile +5 -0
  70. data/resources/skel/app/grids/cashflow_grid.rb +27 -0
  71. data/resources/skel/app/grids/monthly_income_and_expenses_grid.rb +25 -0
  72. data/resources/skel/app/grids/wealth_growth_grid.rb +35 -0
  73. data/resources/skel/app/plots/cashflow.yml +33 -0
  74. data/resources/skel/app/plots/monthly-income-and-expenses.yml +17 -0
  75. data/resources/skel/app/plots/wealth-growth.yml +20 -0
  76. data/resources/skel/config/csv-format-acme-checking.yml +9 -0
  77. data/resources/skel/config/google-secrets.yml +5 -0
  78. data/resources/skel/config/rvgp.yml +0 -0
  79. data/resources/skel/journals/prices.db +0 -0
  80. data/rvgp.gemspec +6 -0
  81. data/test/assets/ledger_total_monthly_liabilities_with_empty.xml +383 -0
  82. data/test/assets/ledger_total_monthly_liabilities_with_empty2.xml +428 -0
  83. data/test/test_command_base.rb +61 -0
  84. data/test/test_commodity.rb +270 -0
  85. data/test/test_csv_reconciler.rb +60 -0
  86. data/test/test_currency.rb +24 -0
  87. data/test/test_fake_feed.rb +228 -0
  88. data/test/test_fake_journal.rb +98 -0
  89. data/test/test_fake_reconciler.rb +60 -0
  90. data/test/test_journal_parse.rb +545 -0
  91. data/test/test_ledger.rb +102 -0
  92. data/test/test_plot.rb +133 -0
  93. data/test/test_posting.rb +50 -0
  94. data/test/test_pricer.rb +139 -0
  95. data/test/test_pta_adapter.rb +575 -0
  96. data/test/test_utilities.rb +45 -0
  97. metadata +268 -0
@@ -0,0 +1,428 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <ledger version="197378">
3
+ <commodities>
4
+ <commodity flags="P">
5
+ <symbol/>
6
+ </commodity>
7
+ <commodity flags="PS">
8
+ <symbol>$</symbol>
9
+ </commodity>
10
+ </commodities>
11
+ <accounts>
12
+ <account id="000055807ebc1c80">
13
+ <name/>
14
+ <fullname/>
15
+ <account-total>
16
+ <amount>
17
+ <commodity flags="PS">
18
+ <symbol>$</symbol>
19
+ </commodity>
20
+ <quantity>-46935.86</quantity>
21
+ </amount>
22
+ </account-total>
23
+ <account id="000055807ebd2390">
24
+ <name>Personal</name>
25
+ <fullname>Personal</fullname>
26
+ <account-total>
27
+ <amount>
28
+ <commodity flags="PS">
29
+ <symbol>$</symbol>
30
+ </commodity>
31
+ <quantity>-46935.86</quantity>
32
+ </amount>
33
+ </account-total>
34
+ <account/>
35
+ <account/>
36
+ <account/>
37
+ <account id="000055807ebe9af0">
38
+ <name>Income</name>
39
+ <fullname>Personal:Income</fullname>
40
+ <account-total>
41
+ <amount>
42
+ <commodity flags="PS">
43
+ <symbol>$</symbol>
44
+ </commodity>
45
+ <quantity>-46935.86</quantity>
46
+ </amount>
47
+ </account-total>
48
+ <account id="000055807ebe9f20">
49
+ <name>ThompsonHegmann</name>
50
+ <fullname>Personal:Income:ThompsonHegmann</fullname>
51
+ <account-amount>
52
+ <amount>
53
+ <commodity flags="PS">
54
+ <symbol>$</symbol>
55
+ </commodity>
56
+ <quantity>-35794.97</quantity>
57
+ </amount>
58
+ </account-amount>
59
+ <account-total>
60
+ <amount>
61
+ <commodity flags="PS">
62
+ <symbol>$</symbol>
63
+ </commodity>
64
+ <quantity>-35794.97</quantity>
65
+ </amount>
66
+ </account-total>
67
+ </account>
68
+ <account id="000055807ebeff90">
69
+ <name>VonRuedenMosciski</name>
70
+ <fullname>Personal:Income:VonRuedenMosciski</fullname>
71
+ <account-amount>
72
+ <amount>
73
+ <commodity flags="PS">
74
+ <symbol>$</symbol>
75
+ </commodity>
76
+ <quantity>-11140.89</quantity>
77
+ </amount>
78
+ </account-amount>
79
+ <account-total>
80
+ <amount>
81
+ <commodity flags="PS">
82
+ <symbol>$</symbol>
83
+ </commodity>
84
+ <quantity>-11140.89</quantity>
85
+ </amount>
86
+ </account-total>
87
+ </account>
88
+ </account>
89
+ <account/>
90
+ </account>
91
+ </account>
92
+ </accounts>
93
+ <transactions>
94
+ <transaction>
95
+ <date>2023/01/01</date>
96
+ <payee>- 23-Jan-31</payee>
97
+ <postings>
98
+ <posting generated="true">
99
+ <account ref="000055807ebe9f20">
100
+ <name>Personal:Income:ThompsonHegmann</name>
101
+ </account>
102
+ <post-amount>
103
+ <amount>
104
+ <commodity flags="PS">
105
+ <symbol>$</symbol>
106
+ </commodity>
107
+ <quantity>-5565.74</quantity>
108
+ </amount>
109
+ </post-amount>
110
+ <total>
111
+ <amount>
112
+ <commodity flags="PS">
113
+ <symbol>$</symbol>
114
+ </commodity>
115
+ <quantity>-5565.74</quantity>
116
+ </amount>
117
+ </total>
118
+ </posting>
119
+ </postings>
120
+ </transaction>
121
+ <transaction>
122
+ <date>2023/02/01</date>
123
+ <payee>- 23-Feb-28</payee>
124
+ <postings>
125
+ <posting generated="true">
126
+ <account ref="000055807ebcfa20">
127
+ <name>&lt;Total&gt;</name>
128
+ </account>
129
+ <post-amount>
130
+ <amount>
131
+ <commodity flags="PS">
132
+ <symbol>$</symbol>
133
+ </commodity>
134
+ <quantity>-18028.51</quantity>
135
+ </amount>
136
+ </post-amount>
137
+ <total>
138
+ <amount>
139
+ <commodity flags="PS">
140
+ <symbol>$</symbol>
141
+ </commodity>
142
+ <quantity>-23594.25</quantity>
143
+ </amount>
144
+ </total>
145
+ </posting>
146
+ </postings>
147
+ </transaction>
148
+ <transaction>
149
+ <date>2023/03/01</date>
150
+ <payee>- 23-Mar-31</payee>
151
+ <postings>
152
+ <posting generated="true">
153
+ <account ref="000055807ebd0120">
154
+ <name>&lt;None&gt;</name>
155
+ </account>
156
+ <post-amount>
157
+ <amount>
158
+ <quantity>0</quantity>
159
+ </amount>
160
+ </post-amount>
161
+ <total>
162
+ <balance>
163
+ <amount>
164
+ <commodity flags="PS">
165
+ <symbol>$</symbol>
166
+ </commodity>
167
+ <quantity>-23594.25</quantity>
168
+ </amount>
169
+ </balance>
170
+ </total>
171
+ </posting>
172
+ </postings>
173
+ </transaction>
174
+ <transaction>
175
+ <date>2023/04/01</date>
176
+ <payee>- 23-Apr-30</payee>
177
+ <postings>
178
+ <posting generated="true">
179
+ <account ref="000055807ebeff90">
180
+ <name>Personal:Income:VonRuedenMosciski</name>
181
+ </account>
182
+ <post-amount>
183
+ <amount>
184
+ <commodity flags="PS">
185
+ <symbol>$</symbol>
186
+ </commodity>
187
+ <quantity>-5356.77</quantity>
188
+ </amount>
189
+ </post-amount>
190
+ <total>
191
+ <balance>
192
+ <amount>
193
+ <commodity flags="PS">
194
+ <symbol>$</symbol>
195
+ </commodity>
196
+ <quantity>-28951.02</quantity>
197
+ </amount>
198
+ </balance>
199
+ </total>
200
+ </posting>
201
+ </postings>
202
+ </transaction>
203
+ <transaction>
204
+ <date>2023/05/01</date>
205
+ <payee>- 23-May-31</payee>
206
+ <postings>
207
+ <posting generated="true">
208
+ <account ref="000055807ebe9f20">
209
+ <name>Personal:Income:ThompsonHegmann</name>
210
+ </account>
211
+ <post-amount>
212
+ <amount>
213
+ <commodity flags="PS">
214
+ <symbol>$</symbol>
215
+ </commodity>
216
+ <quantity>-12371.24</quantity>
217
+ </amount>
218
+ </post-amount>
219
+ <total>
220
+ <balance>
221
+ <amount>
222
+ <commodity flags="PS">
223
+ <symbol>$</symbol>
224
+ </commodity>
225
+ <quantity>-41322.26</quantity>
226
+ </amount>
227
+ </balance>
228
+ </total>
229
+ </posting>
230
+ </postings>
231
+ </transaction>
232
+ <transaction>
233
+ <date>2023/06/01</date>
234
+ <payee>- 23-Jun-30</payee>
235
+ <postings>
236
+ <posting generated="true">
237
+ <account ref="000055807ebe9f20">
238
+ <name>Personal:Income:ThompsonHegmann</name>
239
+ </account>
240
+ <post-amount>
241
+ <amount>
242
+ <commodity flags="PS">
243
+ <symbol>$</symbol>
244
+ </commodity>
245
+ <quantity>-6075.64</quantity>
246
+ </amount>
247
+ </post-amount>
248
+ <total>
249
+ <balance>
250
+ <amount>
251
+ <commodity flags="PS">
252
+ <symbol>$</symbol>
253
+ </commodity>
254
+ <quantity>-47397.9</quantity>
255
+ </amount>
256
+ </balance>
257
+ </total>
258
+ </posting>
259
+ </postings>
260
+ </transaction>
261
+ <transaction>
262
+ <date>2023/07/01</date>
263
+ <payee>- 23-Jul-31</payee>
264
+ <postings>
265
+ <posting generated="true">
266
+ <account ref="000055807ebd0120">
267
+ <name>&lt;None&gt;</name>
268
+ </account>
269
+ <post-amount>
270
+ <amount>
271
+ <quantity>0</quantity>
272
+ </amount>
273
+ </post-amount>
274
+ <total>
275
+ <balance>
276
+ <amount>
277
+ <commodity flags="PS">
278
+ <symbol>$</symbol>
279
+ </commodity>
280
+ <quantity>-47397.9</quantity>
281
+ </amount>
282
+ </balance>
283
+ </total>
284
+ </posting>
285
+ </postings>
286
+ </transaction>
287
+ <transaction>
288
+ <date>2023/08/01</date>
289
+ <payee>- 23-Aug-31</payee>
290
+ <postings>
291
+ <posting generated="true">
292
+ <account ref="000055807ebeff90">
293
+ <name>Personal:Income:VonRuedenMosciski</name>
294
+ </account>
295
+ <post-amount>
296
+ <amount>
297
+ <commodity flags="PS">
298
+ <symbol>$</symbol>
299
+ </commodity>
300
+ <quantity>-5784.12</quantity>
301
+ </amount>
302
+ </post-amount>
303
+ <total>
304
+ <balance>
305
+ <amount>
306
+ <commodity flags="PS">
307
+ <symbol>$</symbol>
308
+ </commodity>
309
+ <quantity>-53182.02</quantity>
310
+ </amount>
311
+ </balance>
312
+ </total>
313
+ </posting>
314
+ </postings>
315
+ </transaction>
316
+ <transaction>
317
+ <date>2023/09/01</date>
318
+ <payee>- 23-Sep-30</payee>
319
+ <postings>
320
+ <posting generated="true">
321
+ <account ref="000055807ebd0120">
322
+ <name>&lt;None&gt;</name>
323
+ </account>
324
+ <post-amount>
325
+ <amount>
326
+ <quantity>0</quantity>
327
+ </amount>
328
+ </post-amount>
329
+ <total>
330
+ <balance>
331
+ <amount>
332
+ <commodity flags="PS">
333
+ <symbol>$</symbol>
334
+ </commodity>
335
+ <quantity>-53182.02</quantity>
336
+ </amount>
337
+ </balance>
338
+ </total>
339
+ </posting>
340
+ </postings>
341
+ </transaction>
342
+ <transaction>
343
+ <date>2023/10/01</date>
344
+ <payee>- 23-Oct-31</payee>
345
+ <postings>
346
+ <posting generated="true">
347
+ <account ref="000055807ebd0120">
348
+ <name>&lt;None&gt;</name>
349
+ </account>
350
+ <post-amount>
351
+ <amount>
352
+ <quantity>0</quantity>
353
+ </amount>
354
+ </post-amount>
355
+ <total>
356
+ <balance>
357
+ <amount>
358
+ <commodity flags="PS">
359
+ <symbol>$</symbol>
360
+ </commodity>
361
+ <quantity>-53182.02</quantity>
362
+ </amount>
363
+ </balance>
364
+ </total>
365
+ </posting>
366
+ </postings>
367
+ </transaction>
368
+ <transaction>
369
+ <date>2023/11/01</date>
370
+ <payee>- 23-Nov-30</payee>
371
+ <postings>
372
+ <posting generated="true">
373
+ <account ref="000055807ebe9f20">
374
+ <name>Personal:Income:ThompsonHegmann</name>
375
+ </account>
376
+ <post-amount>
377
+ <amount>
378
+ <commodity flags="PS">
379
+ <symbol>$</symbol>
380
+ </commodity>
381
+ <quantity>-5485.09</quantity>
382
+ </amount>
383
+ </post-amount>
384
+ <total>
385
+ <balance>
386
+ <amount>
387
+ <commodity flags="PS">
388
+ <symbol>$</symbol>
389
+ </commodity>
390
+ <quantity>-58667.11</quantity>
391
+ </amount>
392
+ </balance>
393
+ </total>
394
+ </posting>
395
+ </postings>
396
+ </transaction>
397
+ <transaction>
398
+ <date>2023/12/01</date>
399
+ <payee>- 23-Dec-31</payee>
400
+ <postings>
401
+ <posting generated="true">
402
+ <account ref="000055807ebe9f20">
403
+ <name>Personal:Income:ThompsonHegmann</name>
404
+ </account>
405
+ <post-amount>
406
+ <amount>
407
+ <commodity flags="PS">
408
+ <symbol>$</symbol>
409
+ </commodity>
410
+ <quantity>-6297.26</quantity>
411
+ </amount>
412
+ </post-amount>
413
+ <total>
414
+ <balance>
415
+ <amount>
416
+ <commodity flags="PS">
417
+ <symbol>$</symbol>
418
+ </commodity>
419
+ <quantity>-64964.37</quantity>
420
+ </amount>
421
+ </balance>
422
+ </total>
423
+ </posting>
424
+ </postings>
425
+ </transaction>
426
+ </transactions>
427
+ </ledger>
428
+
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'minitest/autorun'
5
+
6
+ require_relative '../lib/rvgp'
7
+
8
+ # Minitest class, used to test RVGP::Base::Command
9
+ class TestBaseCommand < Minitest::Test
10
+ def test_remove_options_from_args
11
+ options = [%i[all a], %i[list l], %i[stdout s], [:date, :d, { has_value: true }]].map do |args|
12
+ RVGP::Base::Command::Option.new(*args)
13
+ end
14
+
15
+ assert_equal [{ stdout: true }, %w[target1 target2]],
16
+ RVGP::Base::Command::Option.remove_options_from_args(options, ['--stdout', 'target1', 'target2'])
17
+ assert_equal [{ stdout: true }, %w[target1 target2]],
18
+ RVGP::Base::Command::Option.remove_options_from_args(options, ['target1', '--stdout', 'target2'])
19
+ assert_equal [{ stdout: true }, %w[target1 target2]],
20
+ RVGP::Base::Command::Option.remove_options_from_args(options, ['target1', 'target2', '--stdout'])
21
+
22
+ options << RVGP::Base::Command::Option.new(:date, :d, { has_value: 'DATE' })
23
+
24
+ assert_equal [{ stdout: true, date: '2022-01-01' }, %w[target1 target2]],
25
+ RVGP::Base::Command::Option.remove_options_from_args(
26
+ options, ['-d', '2022-01-01', 'target1', 'target2', '--stdout']
27
+ )
28
+
29
+ assert_equal [{ stdout: true, date: '2022-01-01' }, %w[target1 target2]],
30
+ RVGP::Base::Command::Option.remove_options_from_args(
31
+ options, ['target1', '--date', '2022-01-01', 'target2', '--stdout']
32
+ )
33
+
34
+ assert_equal [{ stdout: true, date: '2022-01-01' }, %w[target1 target2]],
35
+ RVGP::Base::Command::Option.remove_options_from_args(
36
+ options, ['target1', 'target2', '--date=2022-01-01', '--stdout']
37
+ )
38
+
39
+ assert_equal [{ stdout: true, date: '2022-01-01' }, %w[target1 target2]],
40
+ RVGP::Base::Command::Option.remove_options_from_args(
41
+ options, ['target1', 'target2', '--stdout', '-d', '2022-01-01']
42
+ )
43
+
44
+ assert_equal [{ stdout: true, date: '2022-01-01' }, %w[target1 target2]],
45
+ RVGP::Base::Command::Option.remove_options_from_args(
46
+ options, ['--stdout', '--date', '2022-01-01', 'target1', 'target2']
47
+ )
48
+
49
+ # This is just kind of an odd one, make sure we don't try to parse the
50
+ # --random=arg as an option:
51
+ assert_equal [{ date: '2022-01-01' }, ['target1', 'target2', '--random=arg']],
52
+ RVGP::Base::Command::Option.remove_options_from_args(
53
+ options, ['--date', '2022-01-01', 'target1', 'target2', '--random=arg']
54
+ )
55
+
56
+ # Note that date expects a value, yet, is at the end of the string:
57
+ assert_raises RVGP::Base::Command::Option::UnexpectedEndOfArgs do
58
+ RVGP::Base::Command::Option.remove_options_from_args(options, ['--stdout', 'target1', 'target2', '--date'])
59
+ end
60
+ end
61
+ end