rvgp 0.3.2
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 +7 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +23 -0
- data/LICENSE +504 -0
- data/README.md +223 -0
- data/Rakefile +32 -0
- data/bin/rvgp +8 -0
- data/lib/rvgp/application/config.rb +159 -0
- data/lib/rvgp/application/descendant_registry.rb +122 -0
- data/lib/rvgp/application/status_output.rb +139 -0
- data/lib/rvgp/application.rb +170 -0
- data/lib/rvgp/base/command.rb +457 -0
- data/lib/rvgp/base/grid.rb +531 -0
- data/lib/rvgp/base/reader.rb +29 -0
- data/lib/rvgp/base/reconciler.rb +434 -0
- data/lib/rvgp/base/validation.rb +261 -0
- data/lib/rvgp/commands/cashflow.rb +160 -0
- data/lib/rvgp/commands/grid.rb +70 -0
- data/lib/rvgp/commands/ireconcile.rb +95 -0
- data/lib/rvgp/commands/new_project.rb +296 -0
- data/lib/rvgp/commands/plot.rb +41 -0
- data/lib/rvgp/commands/publish_gsheets.rb +83 -0
- data/lib/rvgp/commands/reconcile.rb +58 -0
- data/lib/rvgp/commands/rotate_year.rb +202 -0
- data/lib/rvgp/commands/validate_journal.rb +59 -0
- data/lib/rvgp/commands/validate_system.rb +44 -0
- data/lib/rvgp/commands.rb +160 -0
- data/lib/rvgp/dashboard.rb +252 -0
- data/lib/rvgp/fakers/fake_feed.rb +245 -0
- data/lib/rvgp/fakers/fake_journal.rb +57 -0
- data/lib/rvgp/fakers/fake_reconciler.rb +88 -0
- data/lib/rvgp/fakers/faker_helpers.rb +25 -0
- data/lib/rvgp/gem.rb +80 -0
- data/lib/rvgp/journal/commodity.rb +453 -0
- data/lib/rvgp/journal/complex_commodity.rb +214 -0
- data/lib/rvgp/journal/currency.rb +101 -0
- data/lib/rvgp/journal/journal.rb +141 -0
- data/lib/rvgp/journal/posting.rb +156 -0
- data/lib/rvgp/journal/pricer.rb +267 -0
- data/lib/rvgp/journal.rb +24 -0
- data/lib/rvgp/plot/gnuplot.rb +478 -0
- data/lib/rvgp/plot/google-drive/output_csv.rb +44 -0
- data/lib/rvgp/plot/google-drive/output_google_sheets.rb +434 -0
- data/lib/rvgp/plot/google-drive/sheet.rb +67 -0
- data/lib/rvgp/plot.rb +293 -0
- data/lib/rvgp/pta/hledger.rb +237 -0
- data/lib/rvgp/pta/ledger.rb +308 -0
- data/lib/rvgp/pta.rb +311 -0
- data/lib/rvgp/reconcilers/csv_reconciler.rb +424 -0
- data/lib/rvgp/reconcilers/journal_reconciler.rb +41 -0
- data/lib/rvgp/reconcilers/shorthand/finance_gem_hacks.rb +48 -0
- data/lib/rvgp/reconcilers/shorthand/international_atm.rb +152 -0
- data/lib/rvgp/reconcilers/shorthand/investment.rb +144 -0
- data/lib/rvgp/reconcilers/shorthand/mortgage.rb +195 -0
- data/lib/rvgp/utilities/grid_query.rb +190 -0
- data/lib/rvgp/utilities/yaml.rb +131 -0
- data/lib/rvgp/utilities.rb +44 -0
- data/lib/rvgp/validations/balance_validation.rb +68 -0
- data/lib/rvgp/validations/duplicate_tags_validation.rb +48 -0
- data/lib/rvgp/validations/uncategorized_validation.rb +15 -0
- data/lib/rvgp.rb +66 -0
- data/resources/README.MD/2022-cashflow-google.png +0 -0
- data/resources/README.MD/2022-cashflow.png +0 -0
- data/resources/README.MD/all-wealth-growth-google.png +0 -0
- data/resources/README.MD/all-wealth-growth.png +0 -0
- data/resources/gnuplot/default.yml +80 -0
- data/resources/i18n/en.yml +192 -0
- data/resources/iso-4217-currencies.json +171 -0
- data/resources/skel/Rakefile +5 -0
- data/resources/skel/app/grids/cashflow_grid.rb +27 -0
- data/resources/skel/app/grids/monthly_income_and_expenses_grid.rb +25 -0
- data/resources/skel/app/grids/wealth_growth_grid.rb +35 -0
- data/resources/skel/app/plots/cashflow.yml +33 -0
- data/resources/skel/app/plots/monthly-income-and-expenses.yml +17 -0
- data/resources/skel/app/plots/wealth-growth.yml +20 -0
- data/resources/skel/config/csv-format-acme-checking.yml +9 -0
- data/resources/skel/config/google-secrets.yml +5 -0
- data/resources/skel/config/rvgp.yml +0 -0
- data/resources/skel/journals/prices.db +0 -0
- data/rvgp.gemspec +6 -0
- data/test/assets/ledger_total_monthly_liabilities_with_empty.xml +383 -0
- data/test/assets/ledger_total_monthly_liabilities_with_empty2.xml +428 -0
- data/test/test_command_base.rb +61 -0
- data/test/test_commodity.rb +270 -0
- data/test/test_csv_reconciler.rb +60 -0
- data/test/test_currency.rb +24 -0
- data/test/test_fake_feed.rb +228 -0
- data/test/test_fake_journal.rb +98 -0
- data/test/test_fake_reconciler.rb +60 -0
- data/test/test_journal_parse.rb +545 -0
- data/test/test_ledger.rb +102 -0
- data/test/test_plot.rb +133 -0
- data/test/test_posting.rb +50 -0
- data/test/test_pricer.rb +139 -0
- data/test/test_pta_adapter.rb +575 -0
- data/test/test_utilities.rb +45 -0
- metadata +268 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RVGP
|
|
4
|
+
# This module contains helper methods used throughout RVGP. These are just common
|
|
5
|
+
# codepaths, that have little in common, save for their general utility.
|
|
6
|
+
module Utilities
|
|
7
|
+
# This returns each month in a series from the first date, to the last, in the
|
|
8
|
+
# provided array of dates
|
|
9
|
+
# @overload months_through(date, ...)
|
|
10
|
+
# @param [Array<Date>] date A date, that will be used to calculate the range of months to construct a range from.
|
|
11
|
+
# @param [Array<Date>] ... More dates. This method will automatically select the max and min from the sample
|
|
12
|
+
# provided.
|
|
13
|
+
# @return [Array<Date>] An array, containing a Date, set to the first of every month, in the provided range.
|
|
14
|
+
def months_through(*args)
|
|
15
|
+
dates = args.flatten.uniq.sort
|
|
16
|
+
|
|
17
|
+
ret = []
|
|
18
|
+
unless dates.empty?
|
|
19
|
+
d = Date.new dates.first.year, dates.first.month, 1 # start_at
|
|
20
|
+
while d <= Date.new(dates.last.year, dates.last.month, 1) # end_at
|
|
21
|
+
ret << d
|
|
22
|
+
d = d >> 1
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
ret
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Convert the provided string, into a Regexp. Note that the the ixm suffixes are supported, unlike
|
|
29
|
+
# ruby's Regexp.new(str) method
|
|
30
|
+
# @param [String] str A string, in the 'standard' regexp format: '/Running (?:to|at) the Park/i'
|
|
31
|
+
# @return [Regexp] The conversion to a useable regexp, for the provided string
|
|
32
|
+
def string_to_regex(str)
|
|
33
|
+
if %r{\A/(.*)/([imx]?[imx]?[imx]?)\Z}.match str
|
|
34
|
+
Regexp.new(::Regexp.last_match(1), ::Regexp.last_match(2).chars.map do |c|
|
|
35
|
+
case c
|
|
36
|
+
when 'i' then Regexp::IGNORECASE
|
|
37
|
+
when 'x' then Regexp::EXTENDED
|
|
38
|
+
when 'm' then Regexp::MULTILINE
|
|
39
|
+
end
|
|
40
|
+
end.reduce(:|))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RVGP
|
|
4
|
+
module Validations
|
|
5
|
+
# This validation asserts that the ledger-reported balance, matches a provided
|
|
6
|
+
# balance, on a given day. These balances, should be stipulated in a section
|
|
7
|
+
# of your reconciler, that looks like this:
|
|
8
|
+
# ```
|
|
9
|
+
# balances:
|
|
10
|
+
# '2022-01-01': $ 105.63
|
|
11
|
+
# '2022-09-01': $ 300.29
|
|
12
|
+
# '2022-10-01': $ 400.33
|
|
13
|
+
# ```
|
|
14
|
+
# These balances are expected to come from a bank statement, and this validation
|
|
15
|
+
# ensures that rvgp is matching the records of your financial institution
|
|
16
|
+
class BalanceValidation < RVGP::Base::JournalValidation
|
|
17
|
+
# If there are no checkpoints in the 'balances' line of the reconciler, this
|
|
18
|
+
# fires a warning. If there are checkpoints, then, we scan the register to
|
|
19
|
+
# ensure that the balance of the reconciler.from, on the checkpoint date,
|
|
20
|
+
# matches the ledger/hledger balance, on that date. (and if it doesnt,
|
|
21
|
+
# fires an error)
|
|
22
|
+
def validate
|
|
23
|
+
if reconciler.balances.nil? || reconciler.balances.empty?
|
|
24
|
+
warning! 'No balance checkpoints found.'
|
|
25
|
+
else
|
|
26
|
+
is_account_valid = true
|
|
27
|
+
cite_balances = reconciler.balances.map do |d, expected_balance_s|
|
|
28
|
+
expected_balance = expected_balance_s.to_commodity
|
|
29
|
+
|
|
30
|
+
balances_on_day = pta.balance format('^%s$', reconciler.from),
|
|
31
|
+
depth: 1,
|
|
32
|
+
end: d.to_s,
|
|
33
|
+
file: RVGP.app.config.project_journal_path
|
|
34
|
+
|
|
35
|
+
balances_found = balances_on_day.accounts.map(&:amounts).flatten.find_all do |amount|
|
|
36
|
+
amount.code == expected_balance.code
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
found = if balances_found.empty?
|
|
40
|
+
# Rather than operate from nil, we'll establish that we're '0' of units
|
|
41
|
+
# of the expected symbol
|
|
42
|
+
RVGP::Journal::Commodity.from_symbol_and_amount expected_balance.code, 0
|
|
43
|
+
else
|
|
44
|
+
balances_found.sum
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
found_as_s = if found
|
|
48
|
+
format('Found: %s', found.to_s)
|
|
49
|
+
else
|
|
50
|
+
found = RVGP::Journal::Commodity.from_symbol_and_amount expected_balance.code, 0
|
|
51
|
+
'(Nil)'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
is_valid = expected_balance == found
|
|
55
|
+
is_account_valid = false unless is_valid
|
|
56
|
+
|
|
57
|
+
format('(%<day>s) Expected: %<expected>s %<indicator>s',
|
|
58
|
+
day: d.to_s,
|
|
59
|
+
expected: expected_balance.to_s,
|
|
60
|
+
indicator: RVGP.pastel.send(is_valid ? :green : :red, found_as_s))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
error! 'Failed Checkpoint(s):', cite_balances unless is_account_valid
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RVGP
|
|
4
|
+
module Validations
|
|
5
|
+
# This class implements a journal validation that ensures a given transfer, hasn't
|
|
6
|
+
# been tagged more than once, with the same tag.
|
|
7
|
+
class DuplicateTagsValidation < RVGP::Base::JournalValidation
|
|
8
|
+
# Reviews every transfer, and post, to ensure that there are no tags occurring more than once, in
|
|
9
|
+
# any given entry. Unlike most of the validations in RVGP, this one doesn't use ledger or hledger
|
|
10
|
+
# to validate. This validation parses the file itself, in ruby, and ensures based on the contents.
|
|
11
|
+
def validate
|
|
12
|
+
journal = RVGP::Journal.parse File.read(reconciler.output_file)
|
|
13
|
+
dupe_messages = []
|
|
14
|
+
|
|
15
|
+
journal.postings.each do |posting|
|
|
16
|
+
posting_tag_names = posting.tags.map(&:key)
|
|
17
|
+
found_dupes = posting_tag_names.find_all { |tag| posting_tag_names.count(tag) > 1 }.uniq
|
|
18
|
+
|
|
19
|
+
if found_dupes.empty?
|
|
20
|
+
posting.transfers.each do |transfer|
|
|
21
|
+
transfer_tag_names = transfer.tags.map(&:key) + posting_tag_names
|
|
22
|
+
|
|
23
|
+
found_dupes = transfer_tag_names.find_all { |tag| transfer_tag_names.count(tag) > 1 }.uniq
|
|
24
|
+
|
|
25
|
+
next if found_dupes.empty?
|
|
26
|
+
|
|
27
|
+
dupe_messages << format('Line %<line>d: %<date>s %<desc>s (Transfer: %<tags>s)',
|
|
28
|
+
line: posting.line_number,
|
|
29
|
+
date: posting.date,
|
|
30
|
+
desc: posting.description,
|
|
31
|
+
tags: found_dupes.join(', '))
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
dupe_messages << format('Line %<line>d: %<date>s %<desc>s (%<tags>s)',
|
|
35
|
+
line: posting.line_number,
|
|
36
|
+
date: posting.date,
|
|
37
|
+
desc: posting.description,
|
|
38
|
+
tags: found_dupes.join(','))
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
unless dupe_messages.empty?
|
|
43
|
+
error! 'These postings have been tagged with the same tag, more than once', dupe_messages
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RVGP
|
|
4
|
+
# This module provides a number of basic, and common, validations for use in your projects
|
|
5
|
+
module Validations
|
|
6
|
+
# This class implements a journal validation that ensures there are no uncategorized
|
|
7
|
+
# expenses in the journal
|
|
8
|
+
class UncategorizedValidation < RVGP::Base::JournalValidation
|
|
9
|
+
# Ensures that there is no balance for 'Unknown' categories in a journal
|
|
10
|
+
def validate
|
|
11
|
+
validate_no_balance 'Uncategorized Transactions', 'Unknown'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/rvgp.rb
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'rvgp/utilities/yaml'
|
|
4
|
+
require_relative 'rvgp/application'
|
|
5
|
+
require_relative 'rvgp/commands'
|
|
6
|
+
require_relative 'rvgp/base/reconciler'
|
|
7
|
+
|
|
8
|
+
# NOTE: Reconcilers & shorthand may want to go into a registry system at
|
|
9
|
+
# some point, akin to grids/validations.
|
|
10
|
+
require_relative 'rvgp/reconcilers/csv_reconciler'
|
|
11
|
+
require_relative 'rvgp/reconcilers/journal_reconciler'
|
|
12
|
+
require_relative 'rvgp/reconcilers/shorthand/mortgage'
|
|
13
|
+
require_relative 'rvgp/reconcilers/shorthand/investment'
|
|
14
|
+
require_relative 'rvgp/reconcilers/shorthand/international_atm'
|
|
15
|
+
|
|
16
|
+
require_relative 'rvgp/base/validation'
|
|
17
|
+
|
|
18
|
+
require_relative 'rvgp/journal'
|
|
19
|
+
require_relative 'rvgp/pta/ledger'
|
|
20
|
+
require_relative 'rvgp/pta/hledger'
|
|
21
|
+
|
|
22
|
+
require_relative 'rvgp/base/grid'
|
|
23
|
+
|
|
24
|
+
# Gem Paths / Resources:
|
|
25
|
+
require_relative 'rvgp/gem'
|
|
26
|
+
|
|
27
|
+
I18n.load_path << Dir[RVGP::Gem.root('resources/i18n/*.yml')]
|
|
28
|
+
RVGP::Journal::Currency.currencies_config = RVGP::Gem.root('resources/iso-4217-currencies.json')
|
|
29
|
+
|
|
30
|
+
# The base module, under which all RVGP code is filed
|
|
31
|
+
module RVGP
|
|
32
|
+
# @param from_path [String] The directory path, to an RVGP project.
|
|
33
|
+
# @return [RVGP::Application] The initialized application, that was stored in RVGP.app
|
|
34
|
+
def self.initialize_app(from_path)
|
|
35
|
+
raise StandardError, 'Application is already initialized' if @app
|
|
36
|
+
|
|
37
|
+
@app = Application.new from_path
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [RVGP::Application] The currently-initialized RVGP:Application
|
|
41
|
+
def self.app
|
|
42
|
+
@app
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [Pastel] The global pastel object, used to output to the console.
|
|
46
|
+
def self.pastel
|
|
47
|
+
@pastel ||= Pastel.new enabled: $stdout.tty?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @!attribute [r] self.commands
|
|
51
|
+
# Contains an array of all available objects, with parent of type {RVGP::Base::Command}.
|
|
52
|
+
# @return [Array<RVGP::Base::Command>] the commands that are available in this project
|
|
53
|
+
# @!attribute [r] self.grids
|
|
54
|
+
# Contains an array of all available objects, with parent of type {RVGP::Base::Grid}.<br>
|
|
55
|
+
# **NOTE:** RVGP.app.task_names => Array<String>, will return all grid-building tasks that have been defined in the
|
|
56
|
+
# project.
|
|
57
|
+
# @return [Array<RVGP::Base::Grid>] the grids that are available in this project
|
|
58
|
+
# @!attribute [r] self.journal_validations
|
|
59
|
+
# Contains an array of all available objects, with parent of type {RVGP::Base::JournalValidation}.
|
|
60
|
+
# @return [Array<RVGP::Base::JournalValidation>] the journal validations that are available in this project
|
|
61
|
+
# @!attribute [r] self.system_validations
|
|
62
|
+
# Contains an array of all available objects, with parent of type {RVGP::Base::SystemValidation}.<br>
|
|
63
|
+
# **NOTE:** RVGP.system_validations.task_names => Array<String>, will return all system validation tasks that have
|
|
64
|
+
# been defined in the project.
|
|
65
|
+
# @return [Array<RVGP::Base::SystemValidation>] the system validations that are available in this project
|
|
66
|
+
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
colors:
|
|
2
|
+
base:
|
|
3
|
+
# Solarized Light:
|
|
4
|
+
base03: '#002b36'
|
|
5
|
+
base02: '#073642'
|
|
6
|
+
base01: '#586e75'
|
|
7
|
+
base00: '#657b83'
|
|
8
|
+
base0: '#839496'
|
|
9
|
+
base1: '#93a1a1'
|
|
10
|
+
base2: '#eee8d5'
|
|
11
|
+
base3: '#fdf6e3'
|
|
12
|
+
yellow: '#b58900'
|
|
13
|
+
orange: '#cb4b16'
|
|
14
|
+
red: '#dc322f'
|
|
15
|
+
magenta: '#d33682'
|
|
16
|
+
violet: '#6c71c4'
|
|
17
|
+
blue: '#268bd2'
|
|
18
|
+
cyan: '#2aa198'
|
|
19
|
+
green: '#859900'
|
|
20
|
+
font: :base03
|
|
21
|
+
title: :font
|
|
22
|
+
grid: :base02
|
|
23
|
+
axis: :base02
|
|
24
|
+
key_text: :font
|
|
25
|
+
background: :base3
|
|
26
|
+
series:
|
|
27
|
+
# https://www.heavy.ai/blog/12-color-palettes-for-telling-better-stories-with-your-data
|
|
28
|
+
# Spring Pastels
|
|
29
|
+
- "#7eb0d5"
|
|
30
|
+
- "#fd7f6f"
|
|
31
|
+
- "#b2e061"
|
|
32
|
+
- "#bd7ebe"
|
|
33
|
+
- "#ffb55a"
|
|
34
|
+
- "#ffee65"
|
|
35
|
+
- "#beb9db"
|
|
36
|
+
- "#fdcce5"
|
|
37
|
+
- "#8bd3c7"
|
|
38
|
+
# Retro Metro
|
|
39
|
+
- "#ea5545"
|
|
40
|
+
- "#f46a9b"
|
|
41
|
+
- "#ef9b20"
|
|
42
|
+
- "#edbf33"
|
|
43
|
+
- "#ede15b"
|
|
44
|
+
- "#bdcf32"
|
|
45
|
+
- "#87bc45"
|
|
46
|
+
- "#27aeef"
|
|
47
|
+
# http://www.gnuplotting.org/data/dark2.pal
|
|
48
|
+
- '#1B9E77'
|
|
49
|
+
- '#D95F02'
|
|
50
|
+
- '#7570B3'
|
|
51
|
+
- '#E7298A'
|
|
52
|
+
- '#66A61E'
|
|
53
|
+
- '#E6AB02'
|
|
54
|
+
- '#A6761D'
|
|
55
|
+
# Blue to Yellow
|
|
56
|
+
- "#115f9a"
|
|
57
|
+
- "#1984c5"
|
|
58
|
+
- "#22a7f0"
|
|
59
|
+
- "#48b5c4"
|
|
60
|
+
- "#76c68f"
|
|
61
|
+
- "#a6d75b"
|
|
62
|
+
- "#c9e52f"
|
|
63
|
+
- "#d0ee11"
|
|
64
|
+
- "#d0f400"
|
|
65
|
+
header: |+
|
|
66
|
+
set datafile separator ","
|
|
67
|
+
set title "%{title}" font "sans,11" textcolor rgb "%{title_rgb}" enhanced
|
|
68
|
+
set terminal wxt size 1200,400 persist enhanced font 'sans,10' background rgb '%{background_rgb}'
|
|
69
|
+
set style line 102 lc rgb '%{grid_rgb}' lt 0 lw 1
|
|
70
|
+
set grid back ls 102
|
|
71
|
+
set style line 101 lc rgb '%{axis_rgb}' lt 1 lw 1
|
|
72
|
+
set border 3 front ls 101
|
|
73
|
+
set xtics font ",9"
|
|
74
|
+
set ytics font ",11"
|
|
75
|
+
set timefmt "%%m-%%y"
|
|
76
|
+
set format x "%%b-%%y"
|
|
77
|
+
set format y "$ %%'.0f"
|
|
78
|
+
unset colorbox
|
|
79
|
+
set key on under center textcolor rgb "%{key_text_rgb}" enhanced font 'sans,9'
|
|
80
|
+
set decimal locale
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
en:
|
|
2
|
+
help:
|
|
3
|
+
usage: 'Usage: %{program} [OPTION]... [COMMAND] [TARGET]...'
|
|
4
|
+
indent: ' '
|
|
5
|
+
description: >
|
|
6
|
+
A plain text accounting workflow tool for: (r)econciling, (v)alidating, (g)rid-production and (p)lotting your finances with ruby. See the program github for more details.
|
|
7
|
+
|
|
8
|
+
command_introduction: >
|
|
9
|
+
COMMAND - This is a required parameter. Command-specific options are
|
|
10
|
+
further available, once you've specified a command mode. See the 'Available Commands' section for a list of supported commands.
|
|
11
|
+
target_introduction: >
|
|
12
|
+
TARGET(s) - Depending on which command you select, a list of targets can be supplied. Typically,
|
|
13
|
+
supplying the -l option, in lieu of any targets, will output the targets supported by the command.
|
|
14
|
+
Note that any asterisk encountered in a target parameter, will expand to include all targets that
|
|
15
|
+
can be matched given the provided (target) string.
|
|
16
|
+
command_list_introduction: 'Available Commands:'
|
|
17
|
+
global_option_introduction: >
|
|
18
|
+
Global Options:
|
|
19
|
+
The following options are available to all commands:
|
|
20
|
+
|
|
21
|
+
-d --dir[=PATH] Use the supplied PATH as the active rvgp directory.
|
|
22
|
+
If unsupplied, this option defaults to the basedir of
|
|
23
|
+
the LEDGER_FILE environment variable.
|
|
24
|
+
commands:
|
|
25
|
+
cashflow:
|
|
26
|
+
description: 'Output a convenient dashboard with income/expense flows, based on intention'
|
|
27
|
+
options:
|
|
28
|
+
all: 'Output a dashboard for every intention in the system'
|
|
29
|
+
list: 'List all available intention-tag values'
|
|
30
|
+
date: 'Specify a date to use, when calculatingg the "recent months" to display. Defaults to "today".'
|
|
31
|
+
new_project:
|
|
32
|
+
description: 'Create a new plain text accounting project, populated with random data, in the path specified by --dir.'
|
|
33
|
+
plot:
|
|
34
|
+
description: 'Build one or more gnuplots, based on a grid variant.'
|
|
35
|
+
options:
|
|
36
|
+
all: 'Build all available plots'
|
|
37
|
+
list: 'List all available plots'
|
|
38
|
+
stdout: 'Output build to STDOUT instead of output_file'
|
|
39
|
+
publish_gsheets:
|
|
40
|
+
description: 'Publish plots, both as a spreadsheet, as well as a graph, into a google sheets workbook.'
|
|
41
|
+
options:
|
|
42
|
+
all: 'Publish all available plots'
|
|
43
|
+
list: 'List all available plot variants'
|
|
44
|
+
csvdir: 'Output the provided plots, as csvs, with grid hacks applied, into the specified directory. Mostly useful for debugging.'
|
|
45
|
+
title: 'The title of the Google doc being published. Defaults to "RVGP Finance Report %m/%d/%y %H:%M". '
|
|
46
|
+
sleep: 'Seconds to sleep, between each sheet upload. This sleep prevents Google from aborting the publish, under the auspice of api spamming. Defaults to 5.'
|
|
47
|
+
ireconcile:
|
|
48
|
+
description: 'Open an interactive vim session, to edit and build a reconcile'
|
|
49
|
+
options:
|
|
50
|
+
all: 'Process all available reconcilers'
|
|
51
|
+
list: 'List all available reconcilers'
|
|
52
|
+
vsplit: 'Split the input and output panes vertically, instead of horizontally (the default)'
|
|
53
|
+
grid:
|
|
54
|
+
description: "Generate Grid csv's in build/grids"
|
|
55
|
+
options:
|
|
56
|
+
all: 'Process all available grids'
|
|
57
|
+
list: 'List all available grids'
|
|
58
|
+
reconcile:
|
|
59
|
+
description: 'Create/Update the build/*.journal, based on ./reconcilers/*.yml'
|
|
60
|
+
options:
|
|
61
|
+
stdout: 'Output build to STDOUT instead of output_file'
|
|
62
|
+
all: 'Process all available reconcilers'
|
|
63
|
+
list: 'List all available reconcilers'
|
|
64
|
+
concise: "Concise output mode. Strips output that's unrelated to errors and warnings. (Mostly used by the ireconcile command)"
|
|
65
|
+
rotate_year:
|
|
66
|
+
description: "Rotate the given reconcilers, for a new year. And, move the last year's input files into the historical directory under your project feeds."
|
|
67
|
+
options:
|
|
68
|
+
all: 'Rotate all eligible reconcilers'
|
|
69
|
+
list: 'List reconcilers eligible for rotation'
|
|
70
|
+
validate_journal:
|
|
71
|
+
description: 'Validate reconciled journals, using the app/validations'
|
|
72
|
+
options:
|
|
73
|
+
all: 'Process all available journals'
|
|
74
|
+
list: 'List all available journals'
|
|
75
|
+
validate_system:
|
|
76
|
+
description: 'Run validations on the ledger, once the individual journals are valid'
|
|
77
|
+
options:
|
|
78
|
+
all: 'Process all available system validations'
|
|
79
|
+
list: 'List all available system validations'
|
|
80
|
+
commands:
|
|
81
|
+
cashflow:
|
|
82
|
+
list_targets: 'The following cashflow intentions are available:'
|
|
83
|
+
account: 'Account'
|
|
84
|
+
expenses: 'Expenses'
|
|
85
|
+
income: 'Income'
|
|
86
|
+
cash_flow: 'Cash Flow'
|
|
87
|
+
errors:
|
|
88
|
+
screen_too_small: 'Screen width "%{screen_width}" is too small. Minimum width is %{minimum_width}.'
|
|
89
|
+
unrecognized_path: 'Unrecognized path: %{file}'
|
|
90
|
+
new_project:
|
|
91
|
+
directory_exists_prompt: "The directory \"%{dir}\" already exists. Continuing will overwrite some of its contents. Are you sure you wish to continue creating a new project in this directory? (Type \"Yes\" to continue) : "
|
|
92
|
+
project_name_prompt: "Whose project is this? A person's full name or a company name will work: "
|
|
93
|
+
project_name_confirmation: "You entered \"%{project_name}\". Is that correct? (Type \"Yes\" to continue) : "
|
|
94
|
+
confirm_operation: "Yes"
|
|
95
|
+
operation_aborted: "\"new_project\" project operation aborted"
|
|
96
|
+
completed_banner: "\nThe new project has been generated successfully.\nThough you may want to add the following line to your ~/.bashrc:\n export LEDGER_FILE=\"%{journal_path}\"\n\nYou're ready to begin working on this project. Try cd'ing into its directory, and running `rake`."
|
|
97
|
+
initialize:
|
|
98
|
+
project_directory: "Project directory"
|
|
99
|
+
bank_feeds: 'Randomized bank feeds'
|
|
100
|
+
reconcilers: 'Randomized reconcilers'
|
|
101
|
+
errors:
|
|
102
|
+
missing_app_dir: "An application directory was not provided, and is required. Set this parameter via --dir argument, or via the LEDGER_FILE environment variable"
|
|
103
|
+
directory_exists: "The directory \"%{dir}\" could not be created because it already exists."
|
|
104
|
+
plot:
|
|
105
|
+
target_description: 'Build the %{name} plot file, and its variants'
|
|
106
|
+
rotate_year:
|
|
107
|
+
list_targets: 'The following reconcilers are eligible for annual rotation:'
|
|
108
|
+
operations_header: 'The following command(s) will be executed:'
|
|
109
|
+
operation_rotate: 'Rotate "%{name}"'
|
|
110
|
+
operation_mkdir: 'mkdir %{path}'
|
|
111
|
+
confirm_operation: "Yes"
|
|
112
|
+
confirm_operation_prompt: "Would you like to run the above operations? (Type \"Yes\" to continue) "
|
|
113
|
+
operation_aborted: "\"rotate_year\" project operation aborted"
|
|
114
|
+
operation_element: ' 🟢 %{operation}'
|
|
115
|
+
publish_gsheets:
|
|
116
|
+
errors:
|
|
117
|
+
missing_google_secrets: 'Missing a readable config/google-secrets.yml file in your project directory'
|
|
118
|
+
unable_to_write_to_csvdir: 'Unable to write to path "%{csvdir}"'
|
|
119
|
+
grid:
|
|
120
|
+
list_targets: 'The following grids are available:'
|
|
121
|
+
target_description: '%{description} for %{year}'
|
|
122
|
+
rescan_grids:
|
|
123
|
+
target_description: 'Re-scan the journal directory, and register previously unavaible grid targets into the running build'
|
|
124
|
+
rescan_plots:
|
|
125
|
+
target_description: 'Re-scan the grid directory, and register previously unavaible plot targets into the running build'
|
|
126
|
+
reconcile:
|
|
127
|
+
list_targets: 'The following reconcilers are available:'
|
|
128
|
+
target_description: 'Reconcile the "%{input_file}" journal'
|
|
129
|
+
errors:
|
|
130
|
+
journal_missing: 'Journal(s) Missing.'
|
|
131
|
+
either_concise_or_stdout: 'Either -concise or -stdout mode can be specified. But, alas, not both.'
|
|
132
|
+
validate_journal:
|
|
133
|
+
list_targets: 'The following journal validations are available:'
|
|
134
|
+
target_description: 'Validate the "%{input_file}" journal'
|
|
135
|
+
validate_system:
|
|
136
|
+
list_targets: 'The following system validations are available:'
|
|
137
|
+
|
|
138
|
+
error:
|
|
139
|
+
error: 'Error'
|
|
140
|
+
warning: 'Warning'
|
|
141
|
+
missing_entry_in_prices_db: ": The following entry is missing in the prices database:\n P %{time} %{from} %{to}"
|
|
142
|
+
end_of_args: 'Missing an expected parameter value, in the argument list'
|
|
143
|
+
no_targets: "No targets specified"
|
|
144
|
+
missing_target: "One or more targets not found : %{targets}"
|
|
145
|
+
missing_command: 'No command specified. Try running --help to view the available program modes'
|
|
146
|
+
command_unrecognized: '"%{command}" command is unrecognized. Consult the help page.'
|
|
147
|
+
command_errors: "Unable to %{command}:"
|
|
148
|
+
command_error: " 🟢 %{error}"
|
|
149
|
+
no_application_dir: "Unable to determine the directory of your application. Consider setting the LEDGER_FILE environment variable, or providing a directory via the --dir parameter"
|
|
150
|
+
invalid_application_dir: 'Invalid or missing project found at the directory "%{directory}"'
|
|
151
|
+
status:
|
|
152
|
+
indicators:
|
|
153
|
+
complete: '🟢'
|
|
154
|
+
complete_and: '%{left} & %{right} '
|
|
155
|
+
fill: '.'
|
|
156
|
+
indent: ' '
|
|
157
|
+
truncated: '…'
|
|
158
|
+
attention1: '🟢'
|
|
159
|
+
attention2: ' ▩ '
|
|
160
|
+
commands:
|
|
161
|
+
reconcile:
|
|
162
|
+
icon: '🏗️ '
|
|
163
|
+
header: Building Journals from Feeds
|
|
164
|
+
prefix: Expanding
|
|
165
|
+
generate:
|
|
166
|
+
icon: 🏦
|
|
167
|
+
header: Generating Automatic Transactions
|
|
168
|
+
prefix: Making
|
|
169
|
+
validate_journal:
|
|
170
|
+
icon: 📒
|
|
171
|
+
header: Inspecting Individual Journal Files
|
|
172
|
+
prefix: Validating
|
|
173
|
+
validate_system:
|
|
174
|
+
icon: 📚
|
|
175
|
+
header: Inspecting System State
|
|
176
|
+
prefix: Validating
|
|
177
|
+
grid:
|
|
178
|
+
icon: ▦
|
|
179
|
+
header: Generating Grids
|
|
180
|
+
prefix: Calculating
|
|
181
|
+
plot:
|
|
182
|
+
icon: 📈
|
|
183
|
+
header: Generating Plots
|
|
184
|
+
prefix: Plotting
|
|
185
|
+
publish_gsheets:
|
|
186
|
+
icon: 📑
|
|
187
|
+
header: Publishing to Google Sheets
|
|
188
|
+
prefix: Sheeting
|
|
189
|
+
new_project:
|
|
190
|
+
icon: 📖
|
|
191
|
+
header: New Project
|
|
192
|
+
prefix: Initializing
|