rustfava 0.1.0__py3-none-any.whl
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.
- rustfava/__init__.py +30 -0
- rustfava/_ctx_globals_class.py +55 -0
- rustfava/api_models.py +36 -0
- rustfava/application.py +534 -0
- rustfava/beans/__init__.py +6 -0
- rustfava/beans/abc.py +327 -0
- rustfava/beans/account.py +79 -0
- rustfava/beans/create.py +377 -0
- rustfava/beans/flags.py +20 -0
- rustfava/beans/funcs.py +38 -0
- rustfava/beans/helpers.py +52 -0
- rustfava/beans/ingest.py +75 -0
- rustfava/beans/load.py +31 -0
- rustfava/beans/prices.py +151 -0
- rustfava/beans/protocols.py +82 -0
- rustfava/beans/str.py +454 -0
- rustfava/beans/types.py +63 -0
- rustfava/cli.py +187 -0
- rustfava/context.py +13 -0
- rustfava/core/__init__.py +729 -0
- rustfava/core/accounts.py +161 -0
- rustfava/core/attributes.py +145 -0
- rustfava/core/budgets.py +207 -0
- rustfava/core/charts.py +301 -0
- rustfava/core/commodities.py +37 -0
- rustfava/core/conversion.py +229 -0
- rustfava/core/documents.py +87 -0
- rustfava/core/extensions.py +132 -0
- rustfava/core/fava_options.py +255 -0
- rustfava/core/file.py +542 -0
- rustfava/core/filters.py +484 -0
- rustfava/core/group_entries.py +97 -0
- rustfava/core/ingest.py +509 -0
- rustfava/core/inventory.py +167 -0
- rustfava/core/misc.py +105 -0
- rustfava/core/module_base.py +18 -0
- rustfava/core/number.py +106 -0
- rustfava/core/query.py +180 -0
- rustfava/core/query_shell.py +301 -0
- rustfava/core/tree.py +265 -0
- rustfava/core/watcher.py +219 -0
- rustfava/ext/__init__.py +232 -0
- rustfava/ext/auto_commit.py +61 -0
- rustfava/ext/portfolio_list/PortfolioList.js +34 -0
- rustfava/ext/portfolio_list/__init__.py +29 -0
- rustfava/ext/portfolio_list/templates/PortfolioList.html +15 -0
- rustfava/ext/rustfava_ext_test/RustfavaExtTest.js +42 -0
- rustfava/ext/rustfava_ext_test/__init__.py +207 -0
- rustfava/ext/rustfava_ext_test/templates/RustfavaExtTest.html +45 -0
- rustfava/ext/rustfava_ext_test/templates/RustfavaExtTestInclude.html +1 -0
- rustfava/help/__init__.py +15 -0
- rustfava/help/_index.md +29 -0
- rustfava/help/beancount_syntax.md +156 -0
- rustfava/help/budgets.md +31 -0
- rustfava/help/conversion.md +29 -0
- rustfava/help/extensions.md +111 -0
- rustfava/help/features.md +179 -0
- rustfava/help/filters.md +103 -0
- rustfava/help/import.md +27 -0
- rustfava/help/options.md +289 -0
- rustfava/helpers.py +30 -0
- rustfava/internal_api.py +221 -0
- rustfava/json_api.py +952 -0
- rustfava/plugins/__init__.py +3 -0
- rustfava/plugins/link_documents.py +107 -0
- rustfava/plugins/tag_discovered_documents.py +44 -0
- rustfava/py.typed +0 -0
- rustfava/rustledger/__init__.py +31 -0
- rustfava/rustledger/constants.py +76 -0
- rustfava/rustledger/engine.py +485 -0
- rustfava/rustledger/loader.py +273 -0
- rustfava/rustledger/options.py +202 -0
- rustfava/rustledger/query.py +331 -0
- rustfava/rustledger/types.py +830 -0
- rustfava/serialisation.py +220 -0
- rustfava/static/app.css +2988 -0
- rustfava/static/app.css.map +7 -0
- rustfava/static/app.js +12854 -0
- rustfava/static/app.js.map +7 -0
- rustfava/static/beancount-JFV44ZVZ.css +5 -0
- rustfava/static/beancount-JFV44ZVZ.css.map +7 -0
- rustfava/static/beancount-VTTKRGSK.js +4642 -0
- rustfava/static/beancount-VTTKRGSK.js.map +7 -0
- rustfava/static/bql-MGFRUMBP.js +333 -0
- rustfava/static/bql-MGFRUMBP.js.map +7 -0
- rustfava/static/chunk-E7ZF4ASL.js +23061 -0
- rustfava/static/chunk-E7ZF4ASL.js.map +7 -0
- rustfava/static/chunk-V24TLQHT.js +12673 -0
- rustfava/static/chunk-V24TLQHT.js.map +7 -0
- rustfava/static/favicon.ico +0 -0
- rustfava/static/fira-mono-cyrillic-400-normal-BLAGXRCE.woff2 +0 -0
- rustfava/static/fira-mono-cyrillic-500-normal-EN7JUAAW.woff2 +0 -0
- rustfava/static/fira-mono-cyrillic-ext-400-normal-EX7VARTS.woff2 +0 -0
- rustfava/static/fira-mono-cyrillic-ext-500-normal-ZDPTUPRR.woff2 +0 -0
- rustfava/static/fira-mono-greek-400-normal-COGHKMOA.woff2 +0 -0
- rustfava/static/fira-mono-greek-500-normal-4EN2PKZT.woff2 +0 -0
- rustfava/static/fira-mono-greek-ext-400-normal-DYEQIJH7.woff2 +0 -0
- rustfava/static/fira-mono-greek-ext-500-normal-SG73CVKQ.woff2 +0 -0
- rustfava/static/fira-mono-latin-400-normal-NA3VLV7E.woff2 +0 -0
- rustfava/static/fira-mono-latin-500-normal-YC77GFWD.woff2 +0 -0
- rustfava/static/fira-mono-latin-ext-400-normal-DIKTZ5PW.woff2 +0 -0
- rustfava/static/fira-mono-latin-ext-500-normal-ZWY4UO4V.woff2 +0 -0
- rustfava/static/fira-mono-symbols2-400-normal-UITXT77Q.woff2 +0 -0
- rustfava/static/fira-mono-symbols2-500-normal-VWPC2EFN.woff2 +0 -0
- rustfava/static/fira-sans-cyrillic-400-normal-KLQMBCA6.woff2 +0 -0
- rustfava/static/fira-sans-cyrillic-500-normal-NFG7UD6J.woff2 +0 -0
- rustfava/static/fira-sans-cyrillic-ext-400-normal-GWO44OPC.woff2 +0 -0
- rustfava/static/fira-sans-cyrillic-ext-500-normal-SP47E5SC.woff2 +0 -0
- rustfava/static/fira-sans-greek-400-normal-UMQBTLC3.woff2 +0 -0
- rustfava/static/fira-sans-greek-500-normal-4ZKHN4FQ.woff2 +0 -0
- rustfava/static/fira-sans-greek-ext-400-normal-O2DVJAJZ.woff2 +0 -0
- rustfava/static/fira-sans-greek-ext-500-normal-SK6GNWGO.woff2 +0 -0
- rustfava/static/fira-sans-latin-400-normal-OYYTPMAV.woff2 +0 -0
- rustfava/static/fira-sans-latin-500-normal-SMQPZW5A.woff2 +0 -0
- rustfava/static/fira-sans-latin-ext-400-normal-OAUP3WK5.woff2 +0 -0
- rustfava/static/fira-sans-latin-ext-500-normal-LY3YDR5Y.woff2 +0 -0
- rustfava/static/fira-sans-vietnamese-400-normal-OBMQ72MR.woff2 +0 -0
- rustfava/static/fira-sans-vietnamese-500-normal-Y4NZR5EU.woff2 +0 -0
- rustfava/static/source-code-pro-cyrillic-400-normal-TO22V6M3.woff2 +0 -0
- rustfava/static/source-code-pro-cyrillic-500-normal-OGBWWWYW.woff2 +0 -0
- rustfava/static/source-code-pro-cyrillic-ext-400-normal-XH44UCIA.woff2 +0 -0
- rustfava/static/source-code-pro-cyrillic-ext-500-normal-3Z6MMVM6.woff2 +0 -0
- rustfava/static/source-code-pro-greek-400-normal-OUXXUQWK.woff2 +0 -0
- rustfava/static/source-code-pro-greek-500-normal-JA2Z5UXO.woff2 +0 -0
- rustfava/static/source-code-pro-greek-ext-400-normal-WCDKMX7U.woff2 +0 -0
- rustfava/static/source-code-pro-greek-ext-500-normal-ZHVI4VKW.woff2 +0 -0
- rustfava/static/source-code-pro-latin-400-normal-QOGTXED5.woff2 +0 -0
- rustfava/static/source-code-pro-latin-500-normal-X57QEOLQ.woff2 +0 -0
- rustfava/static/source-code-pro-latin-ext-400-normal-QXC74NBF.woff2 +0 -0
- rustfava/static/source-code-pro-latin-ext-500-normal-QGOY7MTT.woff2 +0 -0
- rustfava/static/source-code-pro-vietnamese-400-normal-NPDCDTBA.woff2 +0 -0
- rustfava/static/source-code-pro-vietnamese-500-normal-M6PJKTR5.woff2 +0 -0
- rustfava/static/tree-sitter-beancount-MLXFQBZ5.wasm +0 -0
- rustfava/static/web-tree-sitter-RNOQ6E74.wasm +0 -0
- rustfava/template_filters.py +64 -0
- rustfava/templates/_journal_table.html +156 -0
- rustfava/templates/_layout.html +26 -0
- rustfava/templates/_query_table.html +88 -0
- rustfava/templates/beancount_file +18 -0
- rustfava/templates/help.html +23 -0
- rustfava/templates/macros/_account_macros.html +5 -0
- rustfava/templates/macros/_commodity_macros.html +13 -0
- rustfava/translations/bg/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/bg/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/ca/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/ca/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/de/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/de/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/es/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/es/LC_MESSAGES/messages.po +619 -0
- rustfava/translations/fa/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/fa/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/fr/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/fr/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/ja/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/ja/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/nl/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/nl/LC_MESSAGES/messages.po +617 -0
- rustfava/translations/pt/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/pt/LC_MESSAGES/messages.po +617 -0
- rustfava/translations/pt_BR/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/pt_BR/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/ru/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/ru/LC_MESSAGES/messages.po +617 -0
- rustfava/translations/sk/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/sk/LC_MESSAGES/messages.po +623 -0
- rustfava/translations/sv/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/sv/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/uk/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/uk/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/zh/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/zh/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/zh_Hant_TW/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/zh_Hant_TW/LC_MESSAGES/messages.po +618 -0
- rustfava/util/__init__.py +157 -0
- rustfava/util/date.py +576 -0
- rustfava/util/excel.py +118 -0
- rustfava/util/ranking.py +79 -0
- rustfava/util/sets.py +18 -0
- rustfava/util/unreachable.py +20 -0
- rustfava-0.1.0.dist-info/METADATA +102 -0
- rustfava-0.1.0.dist-info/RECORD +187 -0
- rustfava-0.1.0.dist-info/WHEEL +5 -0
- rustfava-0.1.0.dist-info/entry_points.txt +2 -0
- rustfava-0.1.0.dist-info/licenses/AUTHORS +11 -0
- rustfava-0.1.0.dist-info/licenses/LICENSE +21 -0
- rustfava-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Conversion
|
|
2
|
+
|
|
3
|
+
In most reports in rustfava, a conversion can be selected with the select dropdown
|
|
4
|
+
at the top of the chart. These conversions will use the prices defined in the
|
|
5
|
+
Beancount file, so these should defined manually or by some plugin (using
|
|
6
|
+
`beancount.plugins.implicit_prices` is recommend to get prices for all costs in
|
|
7
|
+
the Beancount file).
|
|
8
|
+
|
|
9
|
+
- "At Cost" - Show all inventories at cost, e.g., a position of
|
|
10
|
+
`10 STOCK {4 USD}` would be converted to `40 USD`.
|
|
11
|
+
- "At Market Value" - Show all inventories at their current market value, that
|
|
12
|
+
is, convert to the cost currency at the current price. E.g., a position of
|
|
13
|
+
`10 STOCK {4 USD}` would be converted to `50 USD` if the current price of
|
|
14
|
+
`STOCK` is `5 USD`.
|
|
15
|
+
- "Units" - The plain units of all positions, e.g., `10 STOCK` for a position of
|
|
16
|
+
`10 STOCK {4 USD}`.
|
|
17
|
+
- "Converted to X" - Convert to the currency `X`, e.g., a position of
|
|
18
|
+
`10 STOCK {4 USD}` would be converted to `20 X` if the current price of
|
|
19
|
+
`STOCK` is `2 X`. For positions with a price, a conversion via the cost
|
|
20
|
+
currency is attempted if no direct price exists, so the example position would
|
|
21
|
+
also successfully be converted if no price for `STOCK` in `X` exists but both
|
|
22
|
+
a price of `STOCK` in `USD` and a price of `X` in `USD` exists.
|
|
23
|
+
- "Converted to X,Y" - It is also possible to chain conversions to currencies by
|
|
24
|
+
selecting multiple conversions in the dropdown. These conversions are done in
|
|
25
|
+
sequence, a position of `10 STOCK {4 USD}` would first be converted to `X` and
|
|
26
|
+
then this amount in `X` would be converted to `Y`.
|
|
27
|
+
|
|
28
|
+
None of the conversions will silently drop amounts, so if a conversion is not
|
|
29
|
+
possible, the un-converted units are shown.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Extensions
|
|
2
|
+
|
|
3
|
+
Rustfava supports extensions. Extensions allow you to register hooks and generate
|
|
4
|
+
your own report pages.
|
|
5
|
+
|
|
6
|
+
If you use this extension system and need it to do more or need other hooks,
|
|
7
|
+
please open an issue on [GitHub](https://github.com/rustledger/rustfava/issues).
|
|
8
|
+
|
|
9
|
+
A rustfava extension is simply a Python module which contains a class that inherits
|
|
10
|
+
from `RustfavaExtensionBase` from `rustfava.ext`. Invoking an extension is done via the
|
|
11
|
+
`fava-extension` option in the beancount file. Check out `rustfava.ext.auto_commit`
|
|
12
|
+
for an example.
|
|
13
|
+
|
|
14
|
+
Extensions may also contain a report - this is detected when the extension's
|
|
15
|
+
class has a `report_title` attribute. The template for the report should be in a
|
|
16
|
+
`templates` subdirectory with a report matching the class's name. For example,
|
|
17
|
+
check out `rustfava.ext.portfolio_list` which has its template located at
|
|
18
|
+
`rustfava/ext/portfolio_list/templates/PortfolioList.html`.
|
|
19
|
+
|
|
20
|
+
Finally, extensions may contain a Javascript module to be loaded in the
|
|
21
|
+
frontend. The module should be in a Javascript file matching the class's name
|
|
22
|
+
and the extension should have its `has_js_module` attribute set to `True`. The
|
|
23
|
+
module can define functions to be called when different events happen. Take a
|
|
24
|
+
look at `rustfava/ext/portfolio_list/PortfolioList.js` for an example. Currently,
|
|
25
|
+
the following events/functions can be specified:
|
|
26
|
+
|
|
27
|
+
- `init`: is called when a rustfava report is first opened
|
|
28
|
+
- `onPageLoad`: Is called when any page in rustfava is loaded (so on first open and
|
|
29
|
+
on any further navigation).
|
|
30
|
+
- `onExtensionPageLoad`: Is called when the extension report is loaded.
|
|
31
|
+
|
|
32
|
+
The whole extension system should be considered unstable and it might change
|
|
33
|
+
drastically.
|
|
34
|
+
|
|
35
|
+
## Rustfava Extension Setup Options
|
|
36
|
+
|
|
37
|
+
______________________________________________________________________
|
|
38
|
+
|
|
39
|
+
## `fava-extension`
|
|
40
|
+
|
|
41
|
+
A Python module to load as extension. The path of the Beancount file is searched
|
|
42
|
+
in addition to anything on the Python path. Single python files will also be
|
|
43
|
+
searched - so for example a `my_extension.py` could be used by giving
|
|
44
|
+
`my_extension`. Note that Python has a global namespace for currently loaded
|
|
45
|
+
modules, so try avoiding simple names that might coincide with some Python
|
|
46
|
+
library (as well as running rustfava on two files that have different extensions of
|
|
47
|
+
the same name).
|
|
48
|
+
|
|
49
|
+
Extensions allow for an optional configuration options string, whose structure
|
|
50
|
+
is specified by the individual extension.
|
|
51
|
+
|
|
52
|
+
<pre><textarea is="beancount-textarea">
|
|
53
|
+
2010-01-01 custom "fava-extension" "extension-name"
|
|
54
|
+
2010-01-01 custom "fava-extension" "extension-with-options" "{'option': 'config_value'}"</textarea></pre>
|
|
55
|
+
|
|
56
|
+
______________________________________________________________________
|
|
57
|
+
|
|
58
|
+
## Hooks
|
|
59
|
+
|
|
60
|
+
Below is a list of all current hooks.
|
|
61
|
+
|
|
62
|
+
### `after_load_file()`
|
|
63
|
+
|
|
64
|
+
Called after a ledger file has been loaded. Use the `self.ledger` object to
|
|
65
|
+
access the ledger data.
|
|
66
|
+
|
|
67
|
+
______________________________________________________________________
|
|
68
|
+
|
|
69
|
+
### `before_request()`
|
|
70
|
+
|
|
71
|
+
Called when starting to process a request. Use Flask’s `request` object to
|
|
72
|
+
access the request being processed (`from flask import request`).
|
|
73
|
+
|
|
74
|
+
______________________________________________________________________
|
|
75
|
+
|
|
76
|
+
### `after_write_source(path: str, source: str)`
|
|
77
|
+
|
|
78
|
+
Called after the string `source` has been written to the Beancount file at
|
|
79
|
+
`path`.
|
|
80
|
+
|
|
81
|
+
______________________________________________________________________
|
|
82
|
+
|
|
83
|
+
### `after_insert_metadata(entry: Directive, key: str, value: str)`
|
|
84
|
+
|
|
85
|
+
Called after metadata (`key: value`) has been added to an `entry`.
|
|
86
|
+
|
|
87
|
+
______________________________________________________________________
|
|
88
|
+
|
|
89
|
+
### `after_insert_entry(entry: Directive)`
|
|
90
|
+
|
|
91
|
+
Called after an `entry` has been inserted.
|
|
92
|
+
|
|
93
|
+
______________________________________________________________________
|
|
94
|
+
|
|
95
|
+
### `after_entry_modified(entry: Directive, new_lines: str)`
|
|
96
|
+
|
|
97
|
+
Called after an `entry` has been modified, e.g., via the context popup.
|
|
98
|
+
|
|
99
|
+
______________________________________________________________________
|
|
100
|
+
|
|
101
|
+
### `after_delete_entry(entry: Directive)`
|
|
102
|
+
|
|
103
|
+
Called after an `entry` has been deleted, e.g., via the context popup.
|
|
104
|
+
|
|
105
|
+
______________________________________________________________________
|
|
106
|
+
|
|
107
|
+
## Extension attributes
|
|
108
|
+
|
|
109
|
+
### `report_title`
|
|
110
|
+
|
|
111
|
+
Optional attribute to set extension report title used in the sidebar.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# rustfava's features
|
|
2
|
+
|
|
3
|
+
This is an overview of some of the more advanced features that rustfava has to
|
|
4
|
+
offer.
|
|
5
|
+
|
|
6
|
+
## Editor
|
|
7
|
+
|
|
8
|
+
The [editor](../editor) provides a convenient way to edit the source file. If
|
|
9
|
+
you want to use a file different from the main file to be opened by default, use
|
|
10
|
+
the [`default-file`](./options#default-file) option. If you have
|
|
11
|
+
[`insert-entry`](./options#insert-entry) options set, the cursor will by default
|
|
12
|
+
jump to the (date-wise) latest one in the opened file.
|
|
13
|
+
|
|
14
|
+
The editor supports auto-completion for various entities, e.g., account names,
|
|
15
|
+
payees, and tags. Trailing whitespace is highlighted in red. The Tab key in the
|
|
16
|
+
editor can be used for indentation - to escape this keyboard trap, press Escape
|
|
17
|
+
and then Tab directly after it.
|
|
18
|
+
|
|
19
|
+
## Queries
|
|
20
|
+
|
|
21
|
+
On the [Query](../query/) report you can execute queries using the Beancount
|
|
22
|
+
Query Language (BQL). Rustfava uses rustledger's built-in query engine. For an
|
|
23
|
+
explanation of how BQL queries work, see the
|
|
24
|
+
[Beancount Query Language Reference](http://furius.ca/beancount/doc/query).
|
|
25
|
+
|
|
26
|
+
Rustfava displays charts for BQL queries - if they have exactly two columns like the
|
|
27
|
+
following example with the first being a date or string and the second an
|
|
28
|
+
inventory, then a line chart or treemap chart is shown on the query page.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
SELECT
|
|
32
|
+
payee,
|
|
33
|
+
SUM(COST(position)) AS balance
|
|
34
|
+
WHERE
|
|
35
|
+
account ~ 'Expenses'
|
|
36
|
+
GROUP BY payee, account
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Rustfava supports downloading the result of these queries in various file formats.
|
|
40
|
+
By default, only exporting to `csv` is supported. For support of `xlsx` and
|
|
41
|
+
`ods`, install rustfava with the `excel` feature:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
uv pip install rustfava[excel]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Adding Transactions
|
|
48
|
+
|
|
49
|
+
By clicking the `+` button or using the `n` keyboard shortcut you can open a
|
|
50
|
+
form to insert a transaction to your Beancount file. The position that
|
|
51
|
+
transactions are inserted at can be specified in a flexible way using the
|
|
52
|
+
[`insert-entry`](./options#insert-entry) option. If you want to set a bookmark
|
|
53
|
+
to this form, adding `#add-transaction` to any URL in rustfava will open it on load.
|
|
54
|
+
Tags and links can be added in the form by adding them (separated by spaces) to
|
|
55
|
+
the narration field, e.g., `narration #tag ^somelink`.
|
|
56
|
+
|
|
57
|
+
## Up-to-date indicators
|
|
58
|
+
|
|
59
|
+
Rustfava offers colored indicators that can help you keep your accounts up-to-date.
|
|
60
|
+
They are shown next to accounts that have the metadata
|
|
61
|
+
`fava-uptodate-indication: TRUE` set on their Open directive. The colors have
|
|
62
|
+
the following meaning:
|
|
63
|
+
|
|
64
|
+
- green: The last entry for this account is a balance check that passed.
|
|
65
|
+
- red: The last entry is a balance check that failed.
|
|
66
|
+
- yellow: The last entry is not a balance check.
|
|
67
|
+
|
|
68
|
+
In addition, a grey dot will be shown if the account has not been updated in a
|
|
69
|
+
while, as configured by the `uptodate-indicator-grey-lookback-days` option.
|
|
70
|
+
|
|
71
|
+
## Displaying only relevant accounts
|
|
72
|
+
|
|
73
|
+
To help display only the most relevant subset of accounts when managing a large
|
|
74
|
+
number or a deep hierarchy of accounts, Rustfava offers the following options:
|
|
75
|
+
|
|
76
|
+
- `show-closed-accounts`
|
|
77
|
+
- `show-accounts-with-zero-balance`
|
|
78
|
+
- `show-accounts-with-zero-transactions`
|
|
79
|
+
- `collapse-pattern`
|
|
80
|
+
|
|
81
|
+
## Opening an external editor
|
|
82
|
+
|
|
83
|
+
Rustfava can open up your source file in your favorite editor directly from the web
|
|
84
|
+
interface using the `use-external-editor` configuration variable through the
|
|
85
|
+
`beancount://` URL handler. See the
|
|
86
|
+
[Beancount urlscheme](https://github.com/aumayr/beancount_urlscheme) project for
|
|
87
|
+
pre-configured URL handlers for macOS and Cygwin.
|
|
88
|
+
|
|
89
|
+
## Multiple Beancount files
|
|
90
|
+
|
|
91
|
+
When you start rustfava specifying multiple Beancount files, you can click the
|
|
92
|
+
Beancount file name on the top left to switch between the files.
|
|
93
|
+
|
|
94
|
+
## Custom links in the sidebar
|
|
95
|
+
|
|
96
|
+
If you regularly use certain views in rustfava with different filters, you can put
|
|
97
|
+
links to them in the sidebar. Custom links can be put in the Beancount file,
|
|
98
|
+
utilizing the `custom` directive:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
2016-05-04 custom "fava-sidebar-link" "Income 2014" "../income_statement?time=2014"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`"fava-sidebar-link"` specifies that this directive is for a custom sidebar
|
|
105
|
+
link, followed by the title to display in the sidebar (`"Income 2014"` in this
|
|
106
|
+
example), and finally the URL to link to. The URL can be relative, like in the
|
|
107
|
+
example above, or absolute, even linking to an external site.
|
|
108
|
+
|
|
109
|
+
Two frequently used custom links are for showing all Documents and all Notes
|
|
110
|
+
found in the journal:
|
|
111
|
+
|
|
112
|
+
- For all Documents: `/<slug>/journal/?show=document`
|
|
113
|
+
- For all Notes: `/<slug>/journal/?show=note`
|
|
114
|
+
|
|
115
|
+
There is a special URL handler `/jump` which can be used to jump to the current
|
|
116
|
+
page with given URL parameters. For example, `/jump?time=month` will show the
|
|
117
|
+
current page but change the time filter to the current month.
|
|
118
|
+
|
|
119
|
+
## Language
|
|
120
|
+
|
|
121
|
+
You can change the language of the interface by specifying the
|
|
122
|
+
[`language`](./options#language) option. If no option is specified, rustfava tries
|
|
123
|
+
to guess the language from your browser settings.
|
|
124
|
+
|
|
125
|
+
## Documents upload
|
|
126
|
+
|
|
127
|
+
One or more documents can be uploaded by drag and drop on account names or
|
|
128
|
+
Journal rows.
|
|
129
|
+
|
|
130
|
+
### Uploading documents
|
|
131
|
+
|
|
132
|
+
To store a document in a specific account, just drag and drop the file on the
|
|
133
|
+
account name in a tree-table.
|
|
134
|
+
|
|
135
|
+
While still dragging, the background-color of the account name will switch to
|
|
136
|
+
blue, indicating that you can drop a file there.
|
|
137
|
+
|
|
138
|
+
Once dropped, a popup will be shown where you can rename the file before
|
|
139
|
+
storing. If the filename does not already start with a date (`YYYY-MM-DD`), the
|
|
140
|
+
current date will be added as a prefix automatically.
|
|
141
|
+
|
|
142
|
+
The file will be then stored in your Beancount documents folder, in a sub-folder
|
|
143
|
+
named after the account. You can set the path to the Beancount documents folder
|
|
144
|
+
by specifying the `option "documents" "/Users/test/invoices"`-option (absolute
|
|
145
|
+
or relative to your Beancount file) in your Beancount file.
|
|
146
|
+
|
|
147
|
+
Beancount will automatically discover files in your `"documents"`-folders and
|
|
148
|
+
generate Document entries for them.
|
|
149
|
+
|
|
150
|
+
When enabling the `tag_discovered_documents`-plugin, these Document entries will
|
|
151
|
+
be tagged with `#discovered` and can be filtered in the Journal:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
plugin "rustfava.plugins.tag_discovered_documents"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Uploading statements
|
|
158
|
+
|
|
159
|
+
When dropping a file on a transaction (or one of its postings) in the Journal,
|
|
160
|
+
the file will be uploaded as described above, and a `document`-metadata-entry
|
|
161
|
+
inserted for the transaction in your Beancount file.
|
|
162
|
+
|
|
163
|
+
When dropped on the description the subfolder corresponds to the account of the
|
|
164
|
+
first posting.
|
|
165
|
+
|
|
166
|
+
**Note**: Uploading statements modifies your Beancount file!
|
|
167
|
+
|
|
168
|
+
When enabling the `link_documents`-plugin, the Document entries created by
|
|
169
|
+
Beancount (see above) will be tagged with `#linked`, linked to the corresponding
|
|
170
|
+
transaction and can be filtered in the Journal:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
plugin "rustfava.plugins.link_documents"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Exporting
|
|
177
|
+
|
|
178
|
+
The entries that are currently shown in rustfava, with filters applied, can be
|
|
179
|
+
downloaded in Beancount format by clicking the ⬇ (Export) button in the sidebar.
|
rustfava/help/filters.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Filters
|
|
2
|
+
|
|
3
|
+
With the text inputs at the top right of the page, you can filter the entries
|
|
4
|
+
that are displayed in rustfava's reports. If you use multiple filters, the entries
|
|
5
|
+
matching all of them will be selected.
|
|
6
|
+
|
|
7
|
+
## Time
|
|
8
|
+
|
|
9
|
+
Filter entries by their date. You can specify dates and intervals like years,
|
|
10
|
+
quarters, months, weeks, and days (for example `2015`, `2012-Q1`, `2010-10`,
|
|
11
|
+
`2016-W12`, or `2015-06-12`). You can specify a range of dates like
|
|
12
|
+
`2010 - 2012-10` which will display all entries between the start of 2010 and
|
|
13
|
+
the end of October 2012.
|
|
14
|
+
|
|
15
|
+
To refer to dates relative to the current day, you can use the variables `year`,
|
|
16
|
+
`quarter`, `month`, `week`, and `day`. These will be substituted with the
|
|
17
|
+
current date expressed in the respective format, and support addition and
|
|
18
|
+
subtraction. For example you can write `year - day` for all entries in the
|
|
19
|
+
current year up to today, or `year-1 - year` for all entries of the last and
|
|
20
|
+
current year. To prevent subtraction, use parentheses: `(month)-10` refers to
|
|
21
|
+
the 10th of this month, whereas `month-10` would be 10 months ago.
|
|
22
|
+
|
|
23
|
+
### Summarisation of previous balances and conversions
|
|
24
|
+
|
|
25
|
+
When setting a time filter, rustfava does not just filter to the transactions in the
|
|
26
|
+
interval but also summarises transactions in the following ways (using
|
|
27
|
+
Beancount's "clamp" summarisation):
|
|
28
|
+
|
|
29
|
+
- All balances for the Income and Expenses accounts previous to the filtered
|
|
30
|
+
period are transferred to the `account_previous_earnings` ("retained
|
|
31
|
+
earnings") account and all of the other transactions before begin date are
|
|
32
|
+
summarised against the `account_previous_balances` account (usually "opening
|
|
33
|
+
balances"). So the Income and Expenses start with a balance of zero whereas
|
|
34
|
+
Assets and Liabilities accounts start with their accumulated balance.
|
|
35
|
+
- All the entries after the end date are removed.
|
|
36
|
+
- A conversion entry is added to the `account_current_conversions` account for
|
|
37
|
+
the changes occurring within the filtered period.
|
|
38
|
+
|
|
39
|
+
### ISO 8601 Week dates
|
|
40
|
+
|
|
41
|
+
The week-based calendar follows
|
|
42
|
+
[ISO 8601 week-numbering system](https://en.wikipedia.org/wiki/ISO_week_date)
|
|
43
|
+
with each week starting on Mondays and the first week of the ISO week-based year
|
|
44
|
+
being the first week that has the majority of its days in January. Equivalently,
|
|
45
|
+
it is also the week to containing January 4th.
|
|
46
|
+
|
|
47
|
+
Some examples where the ISO week-based calendar differs from the Gregorian
|
|
48
|
+
calendar:
|
|
49
|
+
|
|
50
|
+
- Week 1 of 2025 starts on Monday 30 December 2024 and ends on Sunday 5 January
|
|
51
|
+
2025\. As a result, 30 December 2024 belongs to the year 2025 of the ISO
|
|
52
|
+
week-based calendar, despite being in the year 2024 of the Gregorian calendar.
|
|
53
|
+
- Week 53 of 2020 ends on Sunday 3 January 2021. As a result, 3 January 2021
|
|
54
|
+
belongs to the year 2020 of the ISO week-based calendar, despite being in the
|
|
55
|
+
year 2021 of the Gregorian calendar.
|
|
56
|
+
|
|
57
|
+
Most years of ISO week-based calendars have 52 weeks, but as there are slightly
|
|
58
|
+
more than 52 weeks in a year, some years contain a 53rd week.
|
|
59
|
+
|
|
60
|
+
## Account
|
|
61
|
+
|
|
62
|
+
Filter entries by account, matching any entry this account is part of. The
|
|
63
|
+
filter can be an account name, either the full account name or a component of
|
|
64
|
+
the account name, or a regular expression matching the account name, e.g.
|
|
65
|
+
`.*Company.*` to filter for all that contain `Company`.
|
|
66
|
+
|
|
67
|
+
## Filter by tag, link, payee and other metadata
|
|
68
|
+
|
|
69
|
+
This final filter allows you to filter entries by various attributes.
|
|
70
|
+
|
|
71
|
+
- Filter by `#tag` or `^link`.
|
|
72
|
+
- Filter by amount, such as `= 100.20` or `>= 100` (comparing the absolute of
|
|
73
|
+
the units).
|
|
74
|
+
- Filter by any entry attribute, such as payee `payee:"restaurant"` or narration
|
|
75
|
+
`narration:'Dinner with Joe'`. The argument is a regular expression which
|
|
76
|
+
needs to be quoted (with `'` or `"`) if it contains spaces or special
|
|
77
|
+
characters. If the argument is not a valid regular expression, rustfava will look
|
|
78
|
+
for an exact match instead.
|
|
79
|
+
- Search in payee and narration if no specific entry attribute is given, e.g.
|
|
80
|
+
`"Cash withdrawal"`. For Note directives, the comment will be searched.
|
|
81
|
+
- Filter for entries having certain metadata values: `document:"\.pdf$"`. Note
|
|
82
|
+
that if the entry has an attribute of the same name as the metadata key, the
|
|
83
|
+
filter will apply to the entry attribute, not the metadata value.
|
|
84
|
+
- Exclude entries that match a filter by prepending a `-` to it, e.g. `-#tag` or
|
|
85
|
+
`-(^link #tag)`.
|
|
86
|
+
- To match entries by posting attributes, you can use `any()` and `all()`, e.g.,
|
|
87
|
+
`any(id:'12', account:"Cash$")` for all entries that have at least one posting
|
|
88
|
+
with metadata `id: 12` or account ending in `Cash`, or
|
|
89
|
+
`all(-account:"^Expenses:Food")` to exclude all transactions having a posting
|
|
90
|
+
to the Expenses:Food account. To match by amount, you can use comparison
|
|
91
|
+
operators, e.g. `any(units > 80)` to filter for all entries where one posting
|
|
92
|
+
has a units with an absolute amount greater than 80.
|
|
93
|
+
|
|
94
|
+
These filters can be combined by separating them by spaces to match all entries
|
|
95
|
+
satisfying all given filters or by commas to match all entries satisfying at
|
|
96
|
+
least one of the given filters. In other words, a space acts like an "and" and a
|
|
97
|
+
comma like an "or". As usual, the logical "and" has a higher grouping power than
|
|
98
|
+
"or" and you can use parentheses to group filters.
|
|
99
|
+
|
|
100
|
+
When given regular expressions, Rustfava checks for a match anywhere in the
|
|
101
|
+
corresponding attribute. Matching is always case-insensitive. To find out more
|
|
102
|
+
about the specific syntax rustfava uses, refer to
|
|
103
|
+
[Python's Regular Expression Syntax](https://docs.python.org/3/library/re.html?highlight=match#regular-expression-syntax).
|
rustfava/help/import.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Import
|
|
2
|
+
|
|
3
|
+
Rustfava can use Beancount's import system to semi-automatically import entries into
|
|
4
|
+
your ledger. See [Importing External Data in Beancount](http://furius.ca/beancount/doc/ingest)
|
|
5
|
+
for more information on how to write importers.
|
|
6
|
+
|
|
7
|
+
**Note**: Import functionality requires the beancount compatibility package.
|
|
8
|
+
Install it with: `uv pip install rustfava[beancount-compat]`
|
|
9
|
+
|
|
10
|
+
You can override the hooks that should be run for your importers by specifying a
|
|
11
|
+
variable `HOOKS` with a list of hooks to apply to the list of
|
|
12
|
+
`(filename: str, entries: list[Directive])` tuples. If you want to use
|
|
13
|
+
beangulp-style hooks that take lists of
|
|
14
|
+
`(filename: str, entries: list[Directive], account: str, importer: Importer)`-tuples,
|
|
15
|
+
you can annotate them with the appropriate Python types which rustfava will detect
|
|
16
|
+
and call with these 4-tuples.
|
|
17
|
+
|
|
18
|
+
Set the `import-config` option to point to your import config and set
|
|
19
|
+
`import-dirs` to the directories that contain the files that you want to import.
|
|
20
|
+
And if you wish to save new entries elsewhere than main file - use
|
|
21
|
+
`insert-entry` option.
|
|
22
|
+
|
|
23
|
+
Rustfava currently only supports entries of type `Transaction`, `Balance`, and
|
|
24
|
+
`Note`. Set the special metadata key `__source__` to display the corresponding
|
|
25
|
+
text (CSV-row, XML-fragment, etc.) for the entry in the list of entries to
|
|
26
|
+
import. Note that this metadata (and all other metadata keys starting with an
|
|
27
|
+
underscore) will be stripped before saving the entry to file.
|